> 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?