Hi again,
On 11/15/2015 11:12 AM, Peter Levart wrote:
Hi Mandy,
On 11/15/2015 12:52 AM, Mandy Chung wrote:
I have been thinking what the users would do when there is no caller.
The JDK use of getCallerClass are to:
1. find the caller's class loader for class loader hierarchy check
2. find the caller’s class loader to load something on behalf of the caller
(visibility)
3. looking forward to work with modules, one would want to get the caller’s
module
- to load something on behalf of the caller's module
- to add read edge to the caller’s module before accessing its type
Frameworks would likely do something similar to #2 and #3. #1 is probably
specific to the reflection API and how the security check is defined.
I started to think returning Thread.class isn’t the right answer as it gives an
elevated privileged context. Returning null or Optional.empty() would have
the users to special case it to handle this rare case while it’s not as helpful
as I’d like it to be. NoCaller.class would be in a similar situation that the
users must handle this rare case (ignoring user error).
Thread t1 = new Thread(new Runnable() {
public void run() {
walker.getCallerClass();
}
});
Runnable::run or the entry point of a thread started/attached invoked is the
first java method a thread would call and it’s the proper context for
caller-sensitive API to look at.
If StackWalker::getCallerClass is called from the first java method a thread
invoked (i.e. Runnable::run, static void main, etc), it’s reasonable for
getCallerClass to return that. In the above example, it will return the
anonymous class implementing Runnable.
Well, in above example, it is the j.l.Thread that calls Runnable::run
(from Thread::run), so it will return j.l.Thread.class.
But I see what you mean. The desire is that in the following example:
new Thread() {
@Override public void run() {
walker.getCallerClass(); // ...you would like it to return the
anonymous subclass of j.l.Thread
}
}.start();
And in the following example:
class Test {
public static void main(String[] args) {
walker.getCallerClass(); // ...you would like it to return the
Test.class
}
}
I think this is a good compromise if we consider the anticipated use
cases you describe. If one has any other use case that doesn't fall
into the no-caller-equals-self-caller scenario, she can use walker.walk().
+1
Regards, Peter
OTOH in the described cases, a caller of walker.getCallerClass() is
actually expecting to be called by a Java method, right? So what would
it be if such "caller-sensitive" method demanded to be called by a Java
method and throw IllegalArgumentException("Not called by Java method")
otherwise?
Have you thought of that possibility?
Regards, Peter
If a caller-sensitive API (M calls getCallerClass) wants to differentiate the
bottom frame on the stack vs the caller class calling M, it should call
StackWalker::walk instead.
I’m inclined to have getCallerClass to return a non-null Class<?> and if the
method calling getCallerClass method is the last frame on the stack, it will return
that method instead.
Mandy