Class 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, a SecurityManager is the second-best option. When this is also not possible, the StackTraceElement[] returned by Throwable.getStackTrace() must be used, and its String class name converted to a Class using the slow Class.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 using Throwable.getStackTrace() which is significantly slower due to examination of every virtual frame of execution.

    • 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)  
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    • 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
      • DEFAULT_CALLER_CLASS

        private static final java.lang.Class<?> DEFAULT_CALLER_CLASS
        TODO: Use Object.class.
    • Constructor Detail

      • StackLocator

        private StackLocator()
    • 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)