@CallerSensitive as public API ?

Nick Williams nicholas+openjdk at nicholaswilliams.net
Tue Jun 25 23:44:21 UTC 2013

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.


[1] http://mail.openjdk.java.net/pipermail/core-libs-dev/2013-June/018049.html

More information about the core-libs-dev mailing list