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