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

Reply via email to