org.apache.logging.log4j.core.impl
Class ReflectiveCallerClassUtility

java.lang.Object
  extended by org.apache.logging.log4j.core.impl.ReflectiveCallerClassUtility

public final class ReflectiveCallerClassUtility
extends Object

Utility class that handles the instability of the Sun/OpenJDK sun.reflect.Reflection.getCallerClass(int) method.

Background: This method, available only in the Oracle/Sun/OpenJDK implementations of the Java Virtual Machine, is a much more efficient mechanism for determining the Class of the caller of a particular method. When it is not available, a SecurityManager is the second-best option. When this is also not possible, the StackTraceElement[] returned by Thread.getStackTrace() must be used, and its String class name converted to a Class using the slow Class.forName(java.lang.String).

As of Java 8, the getCallerClass(int) method has been removed from Oracle/OpenJDK and is no longer usable. A back-port of the feature that resulted in this change was made in Java 7u25, but the getCallerClass(int) was left around for that version and deprecated, with the intention of being removed in 7u40. By coincidence, the change actually broke getCallerClass(int) (the return value was inadvertently offset by 1 stack frame). This was actually a good thing, because it made the hundreds of libraries and frameworks relying on this method aware of what the JDK developers were up to.

After much community backlash, the JDK team agreed to restore getCallerClass(int) and keep its existing behavior for the rest of Java 7. However, the method is deprecated in Java 8, supposedly won't be in Java 9 (unless no public API is exposed which may force them to keep it), and so backup options must be used. This class:

IMPORTANT NOTE: This class should not be relied upon. It is considered an internal class and could change at any time, breaking your code if you use it. Specifically, as a possible public API replacement for getCallerClass(int) develops in Java 9, this class is very likely to change or even go away.


Method Summary
static Class<?> getCaller(int depth)
          Reflectively calls getCallerClass(int), compensating for the additional frame on the stack, and compensating for the Java 7u25 bug if necessary.
static boolean isSupported()
          Indicates whether getCallerClass(int) can be used on this JVM.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Method Detail

isSupported

public static boolean isSupported()
Indicates whether getCallerClass(int) can be used on this JVM.

Returns:
true if it can be used. If false, getCaller(int) should not be called. Use a backup mechanism instead.

getCaller

public static Class<?> getCaller(int depth)
Reflectively calls getCallerClass(int), compensating for the additional frame on the stack, and compensating for the Java 7u25 bug if necessary. You should check with isSupported() before using this method.

Parameters:
depth - The depth of the caller to retrieve.
Returns:
the caller class, or null if getCallerClass(int) is not supported.


Copyright © 1999-2014 Apache Software Foundation. All Rights Reserved.
Apache Logging, Apache Log4j, Log4j, Apache, the Apache feather logo, the Apache Logging project logo, and the Apache Log4j logo are trademarks of The Apache Software Foundation.