Class StackWalker

java.lang.Object
java.lang.StackWalker

public final classStackWalkerextendsObject
A stack walker.

Thewalk method opens a sequential stream ofStackFrames for the current thread and then applies the given function to walk theStackFrame stream. The stream reports stack frame elements in order, from the top most frame that represents the execution point at which the stack was generated to the bottom most frame. TheStackFrame stream is closed when thewalk method returns. If an attempt is made to reuse the closed stream,IllegalStateException will be thrown.

Stack walker options configure the stack frame information obtained by aStackWalker. By default, the class name and method information are collected but not theClass reference. The method information can be dropped via theDROP_METHOD_INFO option. TheClass object can be retained for access via theRETAIN_CLASS_REFERENCE option. Stack frames of the reflection API and implementation classes arehidden by default.

StackWalker is thread-safe. Multiple threads can share a singleStackWalker object to traverse its own stack.

API Note:
Examples

1. To find the first caller filtering out a known list of implementation class:

    StackWalker walker = StackWalker.getInstance(Set.of(Option.DROP_METHOD_INFO, Option.RETAIN_CLASS_REFERENCE));    Optional<Class<?>> callerClass = walker.walk(s ->            s.map(StackFrame::getDeclaringClass)             .filter(Predicate.not(implClasses::contains))             .findFirst());

2. To snapshot the top 10 stack frames of the current thread,

    List<StackFrame> stack = StackWalker.getInstance().walk(s -> s.limit(10).toList());
Unless otherwise noted, passing anull argument to a constructor or method in thisStackWalker class will cause aNullPointerException to be thrown.

Since:
9
  • Method Details

    • getInstance

      public static StackWalker getInstance()
      Returns aStackWalker instance.

      ThisStackWalker is configured to skip allhidden frames and noclass reference is retained.

      Returns:
      aStackWalker configured to skip allhidden frames and noclass reference is retained.
    • getInstance

      public static StackWalker getInstance(StackWalker.Option option)
      Returns aStackWalker instance with the given option specifying the stack frame information it can access.
      Parameters:
      option -stack walking option
      Returns:
      aStackWalker configured with the given option
    • getInstance

      public static StackWalker getInstance(Set<StackWalker.Option> options)
      Returns aStackWalker instance with the givenoptions specifying the stack frame information it can access.

      If the givenoptions is empty, thisStackWalker is configured to skip allhidden frames and noclass reference is retained.

      Parameters:
      options -stack walking options
      Returns:
      aStackWalker configured with the given options
    • getInstance

      public static StackWalker getInstance(Set<StackWalker.Option> options, int estimateDepth)
      Returns aStackWalker instance with the givenoptions specifying the stack frame information it can access.

      If the givenoptions is empty, thisStackWalker is configured to skip allhidden frames and noclass reference is retained.

      TheestimateDepth specifies the estimate number of stack frames thisStackWalker will traverse that theStackWalker could use as a hint for the buffer size.

      Parameters:
      options -stack walking options
      estimateDepth - Estimate number of stack frames to be traversed.
      Returns:
      aStackWalker configured with the given options
      Throws:
      IllegalArgumentException - ifestimateDepth <= 0
    • walk

      public <T> T walk(Function<? superStream<StackWalker.StackFrame>, ? extends T> function)
      Applies the given function to the stream ofStackFrames for the current thread, traversing from the top frame of the stack, which is the method calling thiswalk method.

      TheStackFrame stream will be closed when this method returns. When a closedStream<StackFrame> object is reused,IllegalStateException will be thrown.

      API Note:
      For example, to find the first 10 calling frames, first skipping those frames whose declaring class is in packagecom.foo:
      List<StackFrame> frames = StackWalker.getInstance().walk(s ->        s.dropWhile(f -> f.getClassName().startsWith("com.foo."))         .limit(10)         .toList());

      This method takes aFunction accepting aStream<StackFrame>, rather than returning aStream<StackFrame> and allowing the caller to directly manipulate the stream. The Java virtual machine is free to reorganize a thread's control stack, for example, via deoptimization. By taking aFunction parameter, this method allows access to stack frames through a stable view of a thread's control stack.

      Parallel execution is effectively disabled and stream pipeline execution will only occur on the current thread.

      Implementation Note:
      The implementation stabilizes the stack by anchoring a frame specific to the stack walking and ensures that the stack walking is performed above the anchored frame. When the stream object is closed or being reused,IllegalStateException will be thrown.
      Type Parameters:
      T - The type of the result of applying the function to the stream ofstack frame.
      Parameters:
      function - a function that takes a stream ofstack frames and returns a result.
      Returns:
      the result of applying the function to the stream ofstack frame.
    • forEach

      public void forEach(Consumer<? superStackWalker.StackFrame> action)
      Performs the given action on each element ofStackFrame stream of the current thread, traversing from the top frame of the stack, which is the method calling thisforEach method.

      This method is equivalent to calling

      walk(s -> { s.forEach(action); return null; });

      Parameters:
      action - an action to be performed on eachStackFrame of the stack of the current thread
    • getCallerClass

      public Class<?> getCallerClass()
      Gets theClass object of the caller who invoked the method that invokedgetCallerClass.

      This method filtersreflection frames,MethodHandle, andhidden frames regardless of theSHOW_REFLECT_FRAMES andSHOW_HIDDEN_FRAMES options thisStackWalker has been configured with.

      This method should be called when a caller frame is present. If it is called from the bottom most frame on the stack,IllegalCallerException will be thrown.

      This method throwsUnsupportedOperationException if thisStackWalker is not configured with theRETAIN_CLASS_REFERENCE option.

      API Note:
      For example,Util::getResourceBundle loads a resource bundle on behalf of the caller. It invokesgetCallerClass to identify the class whose method calledUtil::getResourceBundle. Then, it obtains the class loader of that class, and uses the class loader to load the resource bundle. The caller class in this example isMyTool.
      class Util {    private final StackWalker walker =        StackWalker.getInstance(Set.of(Option.DROP_METHOD_INFO, Option.RETAIN_CLASS_REFERENCE));    public ResourceBundle getResourceBundle(String bundleName) {        Class<?> caller = walker.getCallerClass();        return ResourceBundle.getBundle(bundleName, Locale.getDefault(), caller.getClassLoader());    }}class MyTool {    private final Util util = new Util();    private void init() {        ResourceBundle rb = util.getResourceBundle("mybundle");    }}
      An equivalent way to find the caller class using thewalk method is as follows (filtering the reflection frames,MethodHandle and hidden frames not shown below):
          Optional<Class<?>> caller = walker.walk(s ->        s.map(StackFrame::getDeclaringClass)         .skip(2)         .findFirst());
      When thegetCallerClass method is called from a method that is the bottom most frame on the stack, for example,static public void main method launched by thejava launcher, or a method invoked from a JNI attached thread,IllegalCallerException is thrown.
      Returns:
      Class object of the caller's caller invoking this method.
      Throws:
      UnsupportedOperationException - if thisStackWalker is not configured withOption.RETAIN_CLASS_REFERENCE.
      IllegalCallerException - if there is no caller frame, i.e. when thisgetCallerClass method is called from a method which is the last frame on the stack.