Class StackLocator
- java.lang.Object
-
- org.apache.logging.log4j.util.StackLocator
-
public final class StackLocator extends java.lang.Object
Consider this class private. Provides various methods to determine the caller class.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, aSecurityManager
is the second-best option. When this is also not possible, theStackTraceElement[]
returned byThrowable.getStackTrace()
must be used, and itsString
class name converted to aClass
using the slowClass.forName(java.lang.String)
(which can add an extra microsecond or more for each invocation depending on the runtime ClassLoader hierarchy).During Java 8 development, the
sun.reflect.Reflection.getCallerClass(int)
was removed from OpenJDK, and this change was back-ported to Java 7 in version 1.7.0_25 which changed the behavior of the call and caused it to be off by one stack frame. This turned out to be beneficial for the survival of this API as the change broke hundreds of libraries and frameworks relying on the API which brought much more attention to the intended API removal.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, and current Java 9 development has not addressed this API. Therefore, the functionality of this class cannot be relied upon for all future versions of Java. It does, however, work just fine in Sun JDK 1.6, OpenJDK 1.6, Oracle/OpenJDK 1.7, and Oracle/OpenJDK 1.8. Other Java environments may fall back to usingThrowable.getStackTrace()
which is significantly slower due to examination of every virtual frame of execution.
-
-
Field Summary
Fields Modifier and Type Field Description private static java.lang.Class<?>
DEFAULT_CALLER_CLASS
TODO: Use Object.class.private static java.lang.reflect.Method
GET_CALLER_CLASS_METHOD
private static StackLocator
INSTANCE
(package private) static int
JDK_7U25_OFFSET
TODO Consider removing now that we require Java 8.
-
Constructor Summary
Constructors Modifier Constructor Description private
StackLocator()
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description java.lang.StackTraceElement
calcLocation(java.lang.String fqcnOfLogger)
java.lang.Class<?>
getCallerClass(int depth)
Gets the Class of the method that called this method at the location up the call stack by the given stack frame depth.java.lang.Class<?>
getCallerClass(java.lang.Class<?> anchor)
java.lang.Class<?>
getCallerClass(java.lang.Class<?> sentinelClass, java.util.function.Predicate<java.lang.Class<?>> callerPredicate)
java.lang.Class<?>
getCallerClass(java.lang.String fqcn, java.lang.String pkg)
java.util.Deque<java.lang.Class<?>>
getCurrentStackTrace()
static StackLocator
getInstance()
Gets the singleton instance.java.lang.StackTraceElement
getStackTraceElement(int depth)
private boolean
isValid(java.lang.StackTraceElement element)
-
-
-
Field Detail
-
JDK_7U25_OFFSET
static final int JDK_7U25_OFFSET
TODO Consider removing now that we require Java 8.
-
GET_CALLER_CLASS_METHOD
private static final java.lang.reflect.Method GET_CALLER_CLASS_METHOD
-
INSTANCE
private static final StackLocator INSTANCE
-
DEFAULT_CALLER_CLASS
private static final java.lang.Class<?> DEFAULT_CALLER_CLASS
TODO: Use Object.class.
-
-
Method Detail
-
getInstance
public static StackLocator getInstance()
Gets the singleton instance.- Returns:
- the singleton instance.
-
getCallerClass
public java.lang.Class<?> getCallerClass(java.lang.Class<?> sentinelClass, java.util.function.Predicate<java.lang.Class<?>> callerPredicate)
-
getCallerClass
public java.lang.Class<?> getCallerClass(int depth)
Gets the Class of the method that called this method at the location up the call stack by the given stack frame depth.This method returns
null
if:sun.reflect.Reflection.getCallerClass(int)
is not present.- An exception is caught calling
sun.reflect.Reflection.getCallerClass(int)
.
- Parameters:
depth
- The stack frame count to walk.- Returns:
- A class or null.
- Throws:
java.lang.IndexOutOfBoundsException
- if depth is negative.
-
getCallerClass
public java.lang.Class<?> getCallerClass(java.lang.String fqcn, java.lang.String pkg)
-
getCallerClass
public java.lang.Class<?> getCallerClass(java.lang.Class<?> anchor)
-
getCurrentStackTrace
public java.util.Deque<java.lang.Class<?>> getCurrentStackTrace()
-
calcLocation
public java.lang.StackTraceElement calcLocation(java.lang.String fqcnOfLogger)
-
getStackTraceElement
public java.lang.StackTraceElement getStackTraceElement(int depth)
-
isValid
private boolean isValid(java.lang.StackTraceElement element)
-
-