Re: @CallerSensitive as public API ?
Hi Peter, I have been very busy on other high priority works and didn't have time to look into this request. I filed 8020968 and 8020785 so that others can help follow up and follow up (I'll be on vacation this Wed). Class.getCallerClass and @CallerSensitive is clearly one option to replace sun.reflect.Reflection.getCallerClass. I'm not precluding this option at all. This would require further investigation and it's not a small task that includes spec work (might have impact to JVM spec), whether implementable by all Java SE implementation, JCK tests, security and there will be subtle issues to consider when defining the specification etc. It seems that this option requires more work than what we can take in jdk8. For your specific use case, the other option we can explore to satisfy your use case is to define a static method to use the caller's class to find the resources. You guessed what I have in mind. Take your example you use below, if the stack looks like this: Class.getCallerResource(name) Resources.getIcon(name) MyClass.someMethod Class.getCallerResource(String name) will be equivalent to calling: Class? caller = sun.reflect.Reflection.getCallerClass(); caller.getResource(name); I'll need to find if there is anyone who can help look into these options. Your help and contribution is very welcome. Mandy On 7/22/2013 2:57 AM, Peter Levart wrote: Hi Mandy, I wonder what API you had in mind. Currently we have ClassLoader and Class instance methods to load resources which are quite low-level in the sense that they require full or relative path to the resource and they return either URL or InputStream. So they usually get wrapped by utilities implementing special search strategies and/or resource un-marshaling. For example, imagine one would like to locate resource using the caller class' ClassLoader using the resource path composed of the package name of the caller class replacing dots with slashes and specified resource name appended, then load the content of the resource into a BufferedImage and construct an Icon from it, wrapping any IOException thrown with some unchecked exception: package my.pkg; class MyClass { void someMethod() { // a static utility method: Icon saveIcon = Resources.getIcon(save-icon.png); // that does the following: Icon saveIcon; try { saveIcon = new ImageIcon(ImageIO.read(MyClass.class.getResource(save-icon.png))); } catch (IOException e) { throw new RuntimeException(e); } I don't suggest creating such APIs in the JDK, just enabling them. So what would it take for an API in ClassLoader or Class to enable creating an API like Resources.getIcon() presented above? I guess a static method like Class.getCallerClass() would do, but I have a feeling this is something that is flagged as sensitive by the security team, right? So what about Class.getCallerClassResource(String name)? This would not locate the resource on behalf of the directly calling class, but the class that is calling some method that is calling this method. Regards, Peter P.S. I still don't know why would method like Class.getCallerClass() be so security sensitive? In order for the getCallerClass() to succeed the method calling it would have to be annotated with @CallerSensitive annotation. If a method has such annotation, anyone deciding to call such method is warned in advance that this method is extracting the callers class and using it as it finds fit. There's no danger of untrusted code to sneak it's own @CallerSensitive methods so that unaware code calls them or is it? Does @CallerSensitive work on statically resolved methods or on runtime resolved methods? I mean, if there is some code in some security-sensitive class: Runnable r = r.run(); // where a Runnable instance is provided by untrusted code: class EvilRunnable implements Runnable { @Override @CallerSensitive public void run() { Class? caller = Class.getCallerClass(); // do some things with caller } } Would @CallerSensitive have desired effect as it is implemented currently or would it work only if Runnable.run() interface method was annotated? On 6/25/2013 6:50 PM, Peter Levart wrote: Hi, I know that @CallerSensitive annotation was introduced to bring some order to JDK internal plumbings. It's scope was to support JDK internal usage, so it's use is limited to classes loaded by bootstrap or extension class-loaders. In JDK-internal code it is used mainly for implementing security-sensitive decisions. But since the sun.reflect.Reflection.getCallerClass(int) was public and unrestricted, it found it's way out into user code, where at least I know that it is used in two areas: 1 - to locate callers in the whole call-stack so that their location in class-path can be reported (Log4J is an example) 2 - to locate immediate caller so that some resources
@CallerSensitive as public API ?
I find this issue tangentially related to some open source logging libraries. Some create a stack trace just so they can get the name of the calling Class instance. Example: Logger log = Logger.createLogger(); // for the current class Are there any thoughts to directly exposing sun.reflect.Reflection.getCallerClass() as a public API? -- Cheers, Paul
Re: @CallerSensitive as public API ?
On 07/22/2013 11:22 AM, Paul Benedict wrote: I find this issue tangentially related to some open source logging libraries. Some create a stack trace just so they can get the name of the calling Class instance. Example: Logger log = Logger.createLogger(); // for the current class Are there any thoughts to directly exposing sun.reflect.Reflection.getCallerClass() as a public API? This is somewhat complicated by two factors: the sea of loggers-which-log-to-loggers, and the usage of the data acquired. The common practice is for the outermost layer to pass in its own class name, so that the innermost layer can search back on the call stack to find the last entry before the outermost layer, and use this entry to get not only the class (and method) name, but also the file name and line number from the stack trace entry. -- - DML
@CallerSensitive as public API ?
That's true David. I concur with your description. I was just more interested in the fact that Java has the calling Class available, but there's no API that exposes it. Many developers kind of groan they always have to explicitly specify the current class name through the language. private static Logger = Logger.getLogger(MyClass.class); Some wish this language enhancement: private static Logger = Logger.getLogger(class); But if a runtime solution could be provided where the calling Class is accessible, that's just as handy. Cheers, Paul
Re: @CallerSensitive as public API ?
On 20 Jul 2013, at 16:38, Chris Hegarty chris.hega...@oracle.com wrote: On 20 Jul 2013, at 15:28, Nick Williams nicholas+open...@nicholaswilliams.net wrote: This bug is not available. It can take up to 24hrs for a newly created bug to become available, please check again later. :-( http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=8020968 This bug is now available. -Chris. -Chris. On Jul 19, 2013, at 8:41 PM, Mandy Chung wrote: Peter, FYI. I have filed this RFE: 8020968: Load resource files using the caller's class and class loader http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=8020968 Mandy On 6/25/2013 6:50 PM, Peter Levart wrote: Hi, I know that @CallerSensitive annotation was introduced to bring some order to JDK internal plumbings. It's scope was to support JDK internal usage, so it's use is limited to classes loaded by bootstrap or extension class-loaders. In JDK-internal code it is used mainly for implementing security-sensitive decisions. But since the sun.reflect.Reflection.getCallerClass(int) was public and unrestricted, it found it's way out into user code, where at least I know that it is used in two areas: 1 - to locate callers in the whole call-stack so that their location in class-path can be reported (Log4J is an example) 2 - to locate immediate caller so that some resources associated with it can be located and used (for example localization data in GUI applications) I don't know how wide-spread 1st usecase is, but the 2nd is common, since it's use enables APIs that need not explicitly pass-in the calling class in order to locate resources associated with it (and/or the class-loader of it). So it would be nice to have such supported API in JDK8 at least. I'm asking here, to hear any arguments against making such API supported and public. Are there any security or other issues? If there aren't, what steps should be taken to introduce such API in the JDK8 timeframe? I'm thinking of a no-arg method, say j.l.Class.getCaller() and moving @CallerSensitive to a supported package + enabling it to mark methods in any class (not just system and ext classes)... Regards, Peter
Re: @CallerSensitive as public API ?
On 07/20/2013 03:41 AM, Mandy Chung wrote: Peter, FYI. I have filed this RFE: 8020968: Load resource files using the caller's class and class loader http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=8020968 Mandy Hi Mandy, I wonder what API you had in mind. Currently we have ClassLoader and Class instance methods to load resources which are quite low-level in the sense that they require full or relative path to the resource and they return either URL or InputStream. So they usually get wrapped by utilities implementing special search strategies and/or resource un-marshaling. For example, imagine one would like to locate resource using the caller class' ClassLoader using the resource path composed of the package name of the caller class replacing dots with slashes and specified resource name appended, then load the content of the resource into a BufferedImage and construct an Icon from it, wrapping any IOException thrown with some unchecked exception: package my.pkg; class MyClass { void someMethod() { // a static utility method: Icon saveIcon = Resources.getIcon(save-icon.png); // that does the following: Icon saveIcon; try { saveIcon = new ImageIcon(ImageIO.read(MyClass.class.getResource(save-icon.png))); } catch (IOException e) { throw new RuntimeException(e); } I don't suggest creating such APIs in the JDK, just enabling them. So what would it take for an API in ClassLoader or Class to enable creating an API like Resources.getIcon() presented above? I guess a static method like Class.getCallerClass() would do, but I have a feeling this is something that is flagged as sensitive by the security team, right? So what about Class.getCallerClassResource(String name)? This would not locate the resource on behalf of the directly calling class, but the class that is calling some method that is calling this method. Regards, Peter P.S. I still don't know why would method like Class.getCallerClass() be so security sensitive? In order for the getCallerClass() to succeed the method calling it would have to be annotated with @CallerSensitive annotation. If a method has such annotation, anyone deciding to call such method is warned in advance that this method is extracting the callers class and using it as it finds fit. There's no danger of untrusted code to sneak it's own @CallerSensitive methods so that unaware code calls them or is it? Does @CallerSensitive work on statically resolved methods or on runtime resolved methods? I mean, if there is some code in some security-sensitive class: Runnable r = r.run(); // where a Runnable instance is provided by untrusted code: class EvilRunnable implements Runnable { @Override @CallerSensitive public void run() { Class? caller = Class.getCallerClass(); // do some things with caller } } Would @CallerSensitive have desired effect as it is implemented currently or would it work only if Runnable.run() interface method was annotated? On 6/25/2013 6:50 PM, Peter Levart wrote: Hi, I know that @CallerSensitive annotation was introduced to bring some order to JDK internal plumbings. It's scope was to support JDK internal usage, so it's use is limited to classes loaded by bootstrap or extension class-loaders. In JDK-internal code it is used mainly for implementing security-sensitive decisions. But since the sun.reflect.Reflection.getCallerClass(int) was public and unrestricted, it found it's way out into user code, where at least I know that it is used in two areas: 1 - to locate callers in the whole call-stack so that their location in class-path can be reported (Log4J is an example) 2 - to locate immediate caller so that some resources associated with it can be located and used (for example localization data in GUI applications) I don't know how wide-spread 1st usecase is, but the 2nd is common, since it's use enables APIs that need not explicitly pass-in the calling class in order to locate resources associated with it (and/or the class-loader of it). So it would be nice to have such supported API in JDK8 at least. I'm asking here, to hear any arguments against making such API supported and public. Are there any security or other issues? If there aren't, what steps should be taken to introduce such API in the JDK8 timeframe? I'm thinking of a no-arg method, say j.l.Class.getCaller() and moving @CallerSensitive to a supported package + enabling it to mark methods in any class (not just system and ext classes)... Regards, Peter
Re: @CallerSensitive as public API ?
This bug is not available. On Jul 19, 2013, at 8:41 PM, Mandy Chung wrote: Peter, FYI. I have filed this RFE: 8020968: Load resource files using the caller's class and class loader http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=8020968 Mandy On 6/25/2013 6:50 PM, Peter Levart wrote: Hi, I know that @CallerSensitive annotation was introduced to bring some order to JDK internal plumbings. It's scope was to support JDK internal usage, so it's use is limited to classes loaded by bootstrap or extension class-loaders. In JDK-internal code it is used mainly for implementing security-sensitive decisions. But since the sun.reflect.Reflection.getCallerClass(int) was public and unrestricted, it found it's way out into user code, where at least I know that it is used in two areas: 1 - to locate callers in the whole call-stack so that their location in class-path can be reported (Log4J is an example) 2 - to locate immediate caller so that some resources associated with it can be located and used (for example localization data in GUI applications) I don't know how wide-spread 1st usecase is, but the 2nd is common, since it's use enables APIs that need not explicitly pass-in the calling class in order to locate resources associated with it (and/or the class-loader of it). So it would be nice to have such supported API in JDK8 at least. I'm asking here, to hear any arguments against making such API supported and public. Are there any security or other issues? If there aren't, what steps should be taken to introduce such API in the JDK8 timeframe? I'm thinking of a no-arg method, say j.l.Class.getCaller() and moving @CallerSensitive to a supported package + enabling it to mark methods in any class (not just system and ext classes)... Regards, Peter
Re: @CallerSensitive as public API ?
Peter, FYI. I have filed this RFE: 8020968: Load resource files using the caller's class and class loader http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=8020968 Mandy On 6/25/2013 6:50 PM, Peter Levart wrote: Hi, I know that @CallerSensitive annotation was introduced to bring some order to JDK internal plumbings. It's scope was to support JDK internal usage, so it's use is limited to classes loaded by bootstrap or extension class-loaders. In JDK-internal code it is used mainly for implementing security-sensitive decisions. But since the sun.reflect.Reflection.getCallerClass(int) was public and unrestricted, it found it's way out into user code, where at least I know that it is used in two areas: 1 - to locate callers in the whole call-stack so that their location in class-path can be reported (Log4J is an example) 2 - to locate immediate caller so that some resources associated with it can be located and used (for example localization data in GUI applications) I don't know how wide-spread 1st usecase is, but the 2nd is common, since it's use enables APIs that need not explicitly pass-in the calling class in order to locate resources associated with it (and/or the class-loader of it). So it would be nice to have such supported API in JDK8 at least. I'm asking here, to hear any arguments against making such API supported and public. Are there any security or other issues? If there aren't, what steps should be taken to introduce such API in the JDK8 timeframe? I'm thinking of a no-arg method, say j.l.Class.getCaller() and moving @CallerSensitive to a supported package + enabling it to mark methods in any class (not just system and ext classes)... Regards, Peter
Re: @CallerSensitive as public API ?
We have a use case within our security manager implementation that *can* be solved with the existing getClassContext method, which returns the whole stack, except we don't *need* the whole stack, just one specific frame. Maybe SecurityManager is a good place for this API? As an aside, getClassContext returns a Class[]; maybe it should be changed to Class?[] instead. -- - DML On Jun 25, 2013, at 8:35 PM, Mandy Chung mandy.ch...@oracle.com wrote: On 6/25/13 3:50 AM, Peter Levart wrote: Hi, I know that @CallerSensitive annotation was introduced to bring some order to JDK internal plumbings. It's scope was to support JDK internal usage, so it's use is limited to classes loaded by bootstrap or extension class-loaders. In JDK-internal code it is used mainly for implementing security-sensitive decisions. But since the sun.reflect.Reflection.getCallerClass(int) was public and unrestricted, it found it's way out into user code, where at least I know that it is used in two areas: 1 - to locate callers in the whole call-stack so that their location in class-path can be reported (Log4J is an example) 2 - to locate immediate caller so that some resources associated with it can be located and used (for example localization data in GUI applications) I don't know how wide-spread 1st usecase is, but the 2nd is common, since it's use enables APIs that need not explicitly pass-in the calling class in order to locate resources associated with it (and/or the class-loader of it). So it would be nice to have such supported API in JDK8 at least. It's good to know these use cases. We leave the method in 7 update release so as to allow time for applications to transition and also determine any use case that the SE API should provide if there is no replacement for it. I'm asking here, to hear any arguments against making such API supported and public. Are there any security or other issues? If there aren't, what steps should be taken to introduce such API in the JDK8 timeframe? I'm thinking of a no-arg method, say j.l.Class.getCaller() and moving @CallerSensitive to a supported package + enabling it to mark methods in any class (not just system and ext classes)... Besides providing a method returning the caller's class, I'd like to consider what other options we have and different use cases could be satisfied by different API. For #2, the problem is that the API to find a resource, it requires to use the ClassLoader with the right visibility (the caller's class loader). This is similiar to 8013839 : Enhance Logger API for handling of resource bundles [1]. For example, a static method Class.getResource to use the caller's class loader to find the given resource might be an alternative? About the timeframe, the API freeze date [2] is Oct 10. If the API is simple and small effort (test development, security assessement, etc), there is chance to get that in for jdk8. Mandy [1] http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=8013839 [2] http://openjdk.java.net/projects/jdk8/milestones#API_Interface_Freeze
Re: @CallerSensitive as public API ?
On 6/25/13 5:42 PM, Mandy Chung wrote: On 6/25/13 3:04 PM, David Lloyd wrote: We have a use case within our security manager implementation that *can* be solved with the existing getClassContext method, which returns the whole stack, except we don't *need* the whole stack, just one specific frame. Maybe SecurityManager is a good place for this API? Which frame do you need? How do you use it? Typically it's the frame belonging to whomever called the method on the class. So it's not a search situation, it's a constant offset. As an aside, getClassContext returns a Class[]; maybe it should be changed to Class?[] instead. Ah. I can fix that in my fix for 8007035 [1]. Mandy [1] http://mail.openjdk.java.net/pipermail/core-libs-dev/2013-June/018327.html -- - DML On Jun 25, 2013, at 8:35 PM, Mandy Chung mandy.ch...@oracle.com wrote: On 6/25/13 3:50 AM, Peter Levart wrote: Hi, I know that @CallerSensitive annotation was introduced to bring some order to JDK internal plumbings. It's scope was to support JDK internal usage, so it's use is limited to classes loaded by bootstrap or extension class-loaders. In JDK-internal code it is used mainly for implementing security-sensitive decisions. But since the sun.reflect.Reflection.getCallerClass(int) was public and unrestricted, it found it's way out into user code, where at least I know that it is used in two areas: 1 - to locate callers in the whole call-stack so that their location in class-path can be reported (Log4J is an example) 2 - to locate immediate caller so that some resources associated with it can be located and used (for example localization data in GUI applications) I don't know how wide-spread 1st usecase is, but the 2nd is common, since it's use enables APIs that need not explicitly pass-in the calling class in order to locate resources associated with it (and/or the class-loader of it). So it would be nice to have such supported API in JDK8 at least. It's good to know these use cases. We leave the method in 7 update release so as to allow time for applications to transition and also determine any use case that the SE API should provide if there is no replacement for it. I'm asking here, to hear any arguments against making such API supported and public. Are there any security or other issues? If there aren't, what steps should be taken to introduce such API in the JDK8 timeframe? I'm thinking of a no-arg method, say j.l.Class.getCaller() and moving @CallerSensitive to a supported package + enabling it to mark methods in any class (not just system and ext classes)... Besides providing a method returning the caller's class, I'd like to consider what other options we have and different use cases could be satisfied by different API. For #2, the problem is that the API to find a resource, it requires to use the ClassLoader with the right visibility (the caller's class loader). This is similiar to 8013839 : Enhance Logger API for handling of resource bundles [1]. For example, a static method Class.getResource to use the caller's class loader to find the given resource might be an alternative? About the timeframe, the API freeze date [2] is Oct 10. If the API is simple and small effort (test development, security assessement, etc), there is chance to get that in for jdk8. Mandy [1] http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=8013839 [2] http://openjdk.java.net/projects/jdk8/milestones#API_Interface_Freeze -- - DML
Re: @CallerSensitive as public API ?
On 06/26/2013 03:10 AM, Dr Heinz M. Kabutz wrote: Hi Peter, here is another use case, where someone might want to use this: 3 - in a static context, find out what the class is that you are in. For example, if you want to create a logger, instead of doing this: private static final Logger log = Logger.getLogger(SomeClass.class); we could instead have a magic method that figures out what class this is being called from and then sets the class automatically. There are two other ways to do this, but they are a lot slower than Reflection.getCallerClass(): 1. http://www.javaspecialists.eu/archive/Issue137.html - create an exception and figure out who the calling class is 2. Or we can use the SecurityManager to get us a stack of contexts. For example, in the exercises for my courses, some students had problems with the JUnit plugin. So each test case also contains the main method, but it is always the same: public static void main(String[] args) { UnitTestRunner.run(); } My UnitTestRunner then depends on the security manager to decide what the actual class is and then uses the JUnit4TestAdapter to call the methods: import junit.framework.*; import junit.textui.*; public class UnitTestRunner { private static void run(Class clazz) { System.out.println(Running unit tests for + clazz); TestRunner.run(new JUnit4TestAdapter(clazz)); } public static void run() { MySecurityManager sm = new MySecurityManager(); Class clazz = sm.getClassContext()[2]; run(clazz); } private static class MySecurityManager extends SecurityManager { public Class[] getClassContext() { return super.getClassContext(); } } } Works like a charm. Fortunately this is not affected by the Reflection.getCallerClass() bug. Just my 2c :-) Regards Heinz Hi Heinz, You can also use the JSR 292 Lookup object MethodHandles.lookup().lookupClass() cheers, Rémi
Re: @CallerSensitive as public API ?
Remi Forax wrote: On 06/26/2013 03:10 AM, Dr Heinz M. Kabutz wrote: Hi Peter, here is another use case, where someone might want to use this: 3 - in a static context, find out what the class is that you are in. For example, if you want to create a logger, instead of doing this: private static final Logger log = Logger.getLogger(SomeClass.class); we could instead have a magic method that figures out what class this is being called from and then sets the class automatically. There are two other ways to do this, but they are a lot slower than Reflection.getCallerClass(): 1. http://www.javaspecialists.eu/archive/Issue137.html - create an exception and figure out who the calling class is 2. Or we can use the SecurityManager to get us a stack of contexts. For example, in the exercises for my courses, some students had problems with the JUnit plugin. So each test case also contains the main method, but it is always the same: public static void main(String[] args) { UnitTestRunner.run(); } My UnitTestRunner then depends on the security manager to decide what the actual class is and then uses the JUnit4TestAdapter to call the methods: import junit.framework.*; import junit.textui.*; public class UnitTestRunner { private static void run(Class clazz) { System.out.println(Running unit tests for + clazz); TestRunner.run(new JUnit4TestAdapter(clazz)); } public static void run() { MySecurityManager sm = new MySecurityManager(); Class clazz = sm.getClassContext()[2]; run(clazz); } private static class MySecurityManager extends SecurityManager { public Class[] getClassContext() { return super.getClassContext(); } } } Works like a charm. Fortunately this is not affected by the Reflection.getCallerClass() bug. Just my 2c :-) Regards Heinz Hi Heinz, You can also use the JSR 292 Lookup object MethodHandles.lookup().lookupClass() Brilliant, thanks Rémi! I've learned something new :-) However, in this case it would not work as I need to find the calling class, not the UnitTestRunner class. Is there a way to find out which class called you with MethodHandles? Heinz
@CallerSensitive as public API ?
Hi, I know that @CallerSensitive annotation was introduced to bring some order to JDK internal plumbings. It's scope was to support JDK internal usage, so it's use is limited to classes loaded by bootstrap or extension class-loaders. In JDK-internal code it is used mainly for implementing security-sensitive decisions. But since the sun.reflect.Reflection.getCallerClass(int) was public and unrestricted, it found it's way out into user code, where at least I know that it is used in two areas: 1 - to locate callers in the whole call-stack so that their location in class-path can be reported (Log4J is an example) 2 - to locate immediate caller so that some resources associated with it can be located and used (for example localization data in GUI applications) I don't know how wide-spread 1st usecase is, but the 2nd is common, since it's use enables APIs that need not explicitly pass-in the calling class in order to locate resources associated with it (and/or the class-loader of it). So it would be nice to have such supported API in JDK8 at least. I'm asking here, to hear any arguments against making such API supported and public. Are there any security or other issues? If there aren't, what steps should be taken to introduce such API in the JDK8 timeframe? I'm thinking of a no-arg method, say j.l.Class.getCaller() and moving @CallerSensitive to a supported package + enabling it to mark methods in any class (not just system and ext classes)... Regards, Peter
Re: @CallerSensitive as public API ?
On 6/25/13 3:50 AM, Peter Levart wrote: Hi, I know that @CallerSensitive annotation was introduced to bring some order to JDK internal plumbings. It's scope was to support JDK internal usage, so it's use is limited to classes loaded by bootstrap or extension class-loaders. In JDK-internal code it is used mainly for implementing security-sensitive decisions. But since the sun.reflect.Reflection.getCallerClass(int) was public and unrestricted, it found it's way out into user code, where at least I know that it is used in two areas: 1 - to locate callers in the whole call-stack so that their location in class-path can be reported (Log4J is an example) 2 - to locate immediate caller so that some resources associated with it can be located and used (for example localization data in GUI applications) I don't know how wide-spread 1st usecase is, but the 2nd is common, since it's use enables APIs that need not explicitly pass-in the calling class in order to locate resources associated with it (and/or the class-loader of it). So it would be nice to have such supported API in JDK8 at least. It's good to know these use cases. We leave the method in 7 update release so as to allow time for applications to transition and also determine any use case that the SE API should provide if there is no replacement for it. I'm asking here, to hear any arguments against making such API supported and public. Are there any security or other issues? If there aren't, what steps should be taken to introduce such API in the JDK8 timeframe? I'm thinking of a no-arg method, say j.l.Class.getCaller() and moving @CallerSensitive to a supported package + enabling it to mark methods in any class (not just system and ext classes)... Besides providing a method returning the caller's class, I'd like to consider what other options we have and different use cases could be satisfied by different API. For #2, the problem is that the API to find a resource, it requires to use the ClassLoader with the right visibility (the caller's class loader). This is similiar to 8013839 : Enhance Logger API for handling of resource bundles [1]. For example, a static method Class.getResource to use the caller's class loader to find the given resource might be an alternative? About the timeframe, the API freeze date [2] is Oct 10. If the API is simple and small effort (test development, security assessement, etc), there is chance to get that in for jdk8. Mandy [1] http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=8013839 [2] http://openjdk.java.net/projects/jdk8/milestones#API_Interface_Freeze
Re: @CallerSensitive as public API ?
On Jun 25, 2013, at 5:50 AM, Peter Levart wrote: Hi, I know that @CallerSensitive annotation was introduced to bring some order to JDK internal plumbings. It's scope was to support JDK internal usage, so it's use is limited to classes loaded by bootstrap or extension class-loaders. In JDK-internal code it is used mainly for implementing security-sensitive decisions. But since the sun.reflect.Reflection.getCallerClass(int) was public and unrestricted, it found it's way out into user code, where at least I know that it is used in two areas: 1 - to locate callers in the whole call-stack so that their location in class-path can be reported (Log4J is an example) 2 - to locate immediate caller so that some resources associated with it can be located and used (for example localization data in GUI applications) I don't know how wide-spread 1st usecase is, but the 2nd is common, since it's use enables APIs that need not explicitly pass-in the calling class in order to locate resources associated with it (and/or the class-loader of it). So it would be nice to have such supported API in JDK8 at least. I'm asking here, to hear any arguments against making such API supported and public. Are there any security or other issues? If there aren't, what steps should be taken to introduce such API in the JDK8 timeframe? I'm thinking of a no-arg method, say j.l.Class.getCaller() and moving @CallerSensitive to a supported package + enabling it to mark methods in any class (not just system and ext classes)... Regards, Peter I'm all for making this API public, and I can see many uses and advantages to doing so. I would point out, however, that #1 actually has two parts: 1.A - To identify callers (Class?, not just name) in the _current_ call stack (currently supported, albeit in a difficult-to-use way, using Class?[] SecurityManager#getClassContext()). 1.B - To identify frames (Class?, not just name) in the stack generated _when throwing an exception_ (not currently supported at all). For those of us working on Log4j, #1.B is the biggest priority by orders of magnitude over #1.A and #2. See the existing discussion [1] for more info. I think the current most-viable options on the table (which some people had concerns about) were A) add the Class? to StackTraceElement and B) add a StackFrame class and add a StackFrame[] getStackFrames method to Throwable (similar to StackTraceElement[] getStackTrace()). StackFrame would contain Class? getFrameClass(), Executable getExecutable(), String getFileName(), int getLineNumber(), and boolean isNative(). As for #2, I would say this: @CallerSensitive is awesome; however, you can't annotate a class @CallerSensitive and it be runnable on Java 6. As much as it sucks, major projects like Log4j will have to support Java 6 for at least another 4-5 years. However, you _can_ conditionally use a Java 8 API and the code still be runnable on Java 6 (as long as there's backup code that executes in the absence of this API). So I would ask that there be a getCallerClass or equivalent method that works with an int skipFrames parameter (like now) or returns a Class?[] _in addition to_ a no-arg getCallerClass method that uses @CallerSensitive. My $0.02. Nick [1] http://mail.openjdk.java.net/pipermail/core-libs-dev/2013-June/018049.html
Re: @CallerSensitive as public API ?
Hi Peter, here is another use case, where someone might want to use this: 3 - in a static context, find out what the class is that you are in. For example, if you want to create a logger, instead of doing this: private static final Logger log = Logger.getLogger(SomeClass.class); we could instead have a magic method that figures out what class this is being called from and then sets the class automatically. There are two other ways to do this, but they are a lot slower than Reflection.getCallerClass(): 1. http://www.javaspecialists.eu/archive/Issue137.html - create an exception and figure out who the calling class is 2. Or we can use the SecurityManager to get us a stack of contexts. For example, in the exercises for my courses, some students had problems with the JUnit plugin. So each test case also contains the main method, but it is always the same: public static void main(String[] args) { UnitTestRunner.run(); } My UnitTestRunner then depends on the security manager to decide what the actual class is and then uses the JUnit4TestAdapter to call the methods: import junit.framework.*; import junit.textui.*; public class UnitTestRunner { private static void run(Class clazz) { System.out.println(Running unit tests for + clazz); TestRunner.run(new JUnit4TestAdapter(clazz)); } public static void run() { MySecurityManager sm = new MySecurityManager(); Class clazz = sm.getClassContext()[2]; run(clazz); } private static class MySecurityManager extends SecurityManager { public Class[] getClassContext() { return super.getClassContext(); } } } Works like a charm. Fortunately this is not affected by the Reflection.getCallerClass() bug. Just my 2c :-) Regards Heinz -- Dr Heinz M. Kabutz (PhD CompSci) Author of The Java(tm) Specialists' Newsletter Oracle Java Champion 2005-2013 JavaOne Rock Star Speaker 2012 http://www.javaspecialists.eu Tel: +30 69 75 595 262 Skype: kabutz Peter Levart wrote: Hi, I know that @CallerSensitive annotation was introduced to bring some order to JDK internal plumbings. It's scope was to support JDK internal usage, so it's use is limited to classes loaded by bootstrap or extension class-loaders. In JDK-internal code it is used mainly for implementing security-sensitive decisions. But since the sun.reflect.Reflection.getCallerClass(int) was public and unrestricted, it found it's way out into user code, where at least I know that it is used in two areas: 1 - to locate callers in the whole call-stack so that their location in class-path can be reported (Log4J is an example) 2 - to locate immediate caller so that some resources associated with it can be located and used (for example localization data in GUI applications) I don't know how wide-spread 1st usecase is, but the 2nd is common, since it's use enables APIs that need not explicitly pass-in the calling class in order to locate resources associated with it (and/or the class-loader of it). So it would be nice to have such supported API in JDK8 at least. I'm asking here, to hear any arguments against making such API supported and public. Are there any security or other issues? If there aren't, what steps should be taken to introduce such API in the JDK8 timeframe? I'm thinking of a no-arg method, say j.l.Class.getCaller() and moving @CallerSensitive to a supported package + enabling it to mark methods in any class (not just system and ext classes)... Regards, Peter