> 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.  I think common cases 
would have the entry point to invoke other java methods including 
caller-sensitive ones.

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.

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

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