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