On 11/17/2015 09:50 PM, Mandy Chung wrote:
On Nov 17, 2015, at 11:54 AM, Peter Levart <peter.lev...@gmail.com> wrote:



On 11/16/2015 08:16 PM, Mandy Chung wrote:
On Nov 15, 2015, at 10:59 AM, Peter Levart <peter.lev...@gmail.com>
  wrote:

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?

Are you thinking about a JNI method calling getCallerClass?  Or refer 
getCallerClass being the bottom of the stack?

I don’t see any issue for a JNI method calling getCallerClass and it’s doing:
*     Class<?> caller = walker.walk(s ->
*         s.map(StackFrame::getDeclaringClass)
*          .skip(2)
*          .findFirst());

Mandy

Hi Mandy,

No, I was not thinking of StackWalker::getCallerClass being called by JNI. I was thinking of a 
"caller-sensitive" method calling getCallerClass() and that "caller-sensitive" 
method being called by JNI from a newly attached thread.

1st, I don't think anyone will attempt calling getCallerClass() from the static 
main() method invoked by java launcher. That's silly and need not be supported.
2nd, I don't think anyone will attempt calling getCallerClass() from overridden 
Thread::run() method. That too need not be supported.

So what we are left with are other "caller-sensitive" methods calling 
getCallerClass(). Like for example:

public class Strings {
     public static ResourceBundle getBundle() {
         Class<?> cc = stackWalker.getCallerClass();
         return ResourceBundle.getBundle(cc.getName() + "$Strings", 
Locale.getDefault(), cc.getClassLoader());
     }
}

Such method obviously expects to be called by some Java method. So it may as 
well demand it. By throwing exception if it is called by JNI from newly 
attached thread.

"caller-sensitive" methods could be viewed as taking an implicit parameter - their 
caller. If that parameter is not specified, they could behave like when some other explicit 
parameter was not specified or invalid - throw new IllegalArgumentException("Not called by 
Java method") …

I thought about this case and I consider it the same category as the static 
main method case which is a method being invoked by newly JNI attached thread 
where the entry point is the last frame on the stack.

Right.

   I think common cases would have the entry point to invoke other java methods 
including caller-sensitive ones.

Yes, and that's not a problem, since caller-sensitive methods are invoked by a Java method in this case (be it entry-point or not, it doesn't matter).

I see your point of those methods being abused.

The other alternative I considered is throwing UnsupportedOperationException if 
there is no caller frame, i.e. skip(2) doesn’t exist.  I agree that it’s a 
better option than returning (n-1)-th frame if it’s the last frame on the stack.

Yes, UnsupportedOperationException is maybe even better (not many would think of caller as being an implicit argument).

I will keep returning the thread’s entry point case to return the class of the 
runnable instead of returning Thread.class.

But (as described in my other message), Runnable::run is not an entry point. Thread::run is. And Thread::run (a Java method) delegates to Runnable::run. So in this case Thread.class will be returned as a normal caller (which it really is). Are you thinking of detecting this situation and special-casing it?

Regards, Peter

Mandy

So instead of "pretending" they were called by themselves, which might not be 
right, simply refuse the invocation with exception. I don't think this would hinder any 
such caller-sensitive method in it's utility. More importantly, it would prevent such 
methods from being abused.
You said about possible use-cases for getCallerClass:

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
Abuse: calling such "caller-sensitive" method by JNI from newly-attached thread 
would use the caller-sensitive method's declaring class ClassLoader for hierarchy check - 
wrong!

2. find the caller’s class loader to load something on behalf of the caller 
(visibility)
Abuse: ... would use the caller-sensitive method's declaring class ClassLoader 
to load something - might work, might not

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
Abuse: ...would load something from caller-sensitive method's declaring class 
module - wrong.

- to add read edge to the caller’s module before accessing its type
Abuse: ...would add a read edge to itself before accessing some type - wrong.


In all those cases throwing exception would be the right thing to do.


What do you think?

Reply via email to