Replacement of sun.reflect.Reflection#getCallerClass

Ralph Goers ralph.goers at dslextreme.com
Tue Sep 3 05:48:47 UTC 2013


I just subscribed so I apologize that this message is probably not going to be threaded properly. It seems mailman has no way for me to retrieve a message.

I'd like to add a couple points to what you have below:

1. In addition to Log4j, Logback has been adding this same information to the stack traces it prints for years. [1]
2. Log4j also uses getCallerClass to determine the caller of the getLogger method so that the Logger can be associated with the LoggerContext associated with that classes ClassLoader.  See [2] for a description of the problem and [3] for how Log4j is handling it.

Ralph





[1] https://github.com/qos-ch/logback/blob/master/logback-classic/src/main/java/ch/qos/logback/classic/spi/PackagingDataCalculator.java
[2] http://logback.qos.ch/manual/loggingSeparation.html#tamingStaticRefs
[3] https://svn.apache.org/repos/asf/logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/selector/ClassLoaderContextSelector.java


Mandy Chung mandy.chung at oracle.com 
Mon Sep 2 20:04:14 PDT 2013

Previous message: [PATCH] 4851444: Exposing sun.reflect.Reflection#getCallerClass	as a public API in Java 8
Next message: RFR: JDK-6823527: java.util.logging.Handler has thread safety	issues
Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Hi Nick,

Thanks for the patch.

JEP 176 [1] describes the caller-sensitive method and the need for a 
mechanical checking of caller-sensitive methods.  Also Peter Levart in 
[2] explained the change in MethodHandles.Lookup related to @CS.  I 
assume you understand the rationale behind and the potential security 
issues.  In general defining caller-sensitive API is discouraged.  
Defining a SE supported @CallerSensitive and also getCallerClass API 
poses the risk of "encouraging" developers to implement more @CS methods 
while not fully understand its implication.  It was a non-goal of JEP 
176 to provide @CallerSensitive as a public API and I would suggest not 
to define it as a public API in JDK 8.

While I'll take the time to look at your patch, I would like to restart 
the discussion from the use cases (in which led to what you summarized 
the need of your proposed API [3]):

1. Groovy 1.x and 2.x use the sun.reflect.Reflection.getCallerClass(int 
depth) method to:

  * emulates the way ResourceBundle.getBundle(String, Locale) works.
    Groovy runtime introduces intermediary stack frame between a caller
    and the call to getBundle, these frames needs to be filtered out;
    when looking for the caller classloader.
  * support the annotation @Grab, @Grab allows to specify a dependency
    between a code and a module (using apache ivy under the hood). The
    resolution is done at runtime and require a specific Classloader
    (the GroovyClassLoader), getCallerClass is used to find the class
    loader of the caller, again filtering out the intermediary stack frame.

Groovy 3.x has a different implementation that doesn't need to do stack 
walk to filter its runtime frames and find the caller.

2. Log4j

Log4j offers "extended stack trace" patterns that requires access to a 
Class object when exceptions or stack traces are logged to provide 
additional information for troubleshooting such as the implementation 
version of the Package, code source, etc. It currently uses the 
sun.reflect.Reflection.getCallerClass(int depth) method to find the 
Class object matching the StackTraceElement in a Throwable or stack 
trace. If the sun.reflect.Reflection.getCallerClass(int depth) method 
doesn't exist, it will use SecurityManager.getClassContext().

This approach is not reliable since the HotSpot implementation of 
getCallerClass filters out the frames corresponding to reflection 
machinery (its intent is to find the true caller) whereas a stack trace 
contains all Java frames up to MaxJavaStackTraceDepth (default is 1024). 
When there is no Class object matching a StackTraceElement, it will fall 
back and load the class (does Log4j know which class loader to use?)

Log4j currently works in the absence of the 
sun.reflect.Reflection.getCallerClass(int depth) method but performance 
is a very major issue.

3. APIs on behalf of the caller

For example, locating a resource on behalf of the caller class to avoid 
explicit additional Class and/or ClassLoader parameters.

Please correct/add if I miss anything.

More will be discussed tomorrow.

Mandy
[1] http://openjdk.java.net/jeps/176
[2] 
http://mail.openjdk.java.net/pipermail/core-libs-dev/2013-July/019397.html
[3] 
http://mail.openjdk.java.net/pipermail/core-libs-dev/2013-July/019334.html




More information about the core-libs-dev mailing list