# Class StackWalker

java.lang.Object
java.lang.StackWalker

public final class StackWalker extends Object
A stack walker.

The `walk` method opens a sequential stream of `StackFrame`s for the current thread and then applies the given function to walk the `StackFrame` 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. The `StackFrame` stream is closed when the `walk` 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 a `StackWalker`. By default, the class name and method information are collected but not the `Class reference`. The method information can be dropped via the `DROP_METHOD_INFO` option. The `Class` object can be retained for access via the `RETAIN_CLASS_REFERENCE` option. Stack frames of the reflection API and implementation classes are hidden by default.

`StackWalker` is thread-safe. Multiple threads can share a single `StackWalker` 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 a `null` argument to a constructor or method in this `StackWalker` class will cause a `NullPointerException` to be thrown.
Since:
  9

- ## Nested Class Summary

  Nested Classes
  Modifier and Type
  Class
  Description
  `static enum`
  `StackWalker.Option`
  Stack walker option to configure the stack frame information obtained by a `StackWalker`.
  `static interface`
  `StackWalker.StackFrame`
  A `StackFrame` object represents a method invocation returned by `StackWalker`.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `void`
  `forEach(Consumer<? super StackWalker.StackFrame> action)`
  Performs the given action on each element of `StackFrame` stream of the current thread, traversing from the top frame of the stack, which is the method calling this `forEach` method.
  `Class<?>`
  `getCallerClass()`
  Gets the `Class` object of the caller who invoked the method that invoked `getCallerClass`.
  `static StackWalker`
  `getInstance()`
  Returns a `StackWalker` instance.
  `static StackWalker`
  `getInstance(StackWalker.Option option)`
  Returns a `StackWalker` instance with the given option specifying the stack frame information it can access.
  `static StackWalker`
  `getInstance(Set<StackWalker.Option> options)`
  Returns a `StackWalker` instance with the given `options` specifying the stack frame information it can access.
  `static StackWalker`
  `getInstance(Set<StackWalker.Option> options, int estimateDepth)`
  Returns a `StackWalker` instance with the given `options` specifying the stack frame information it can access.
  `<T> T`
  `walk(Function<? super Stream<StackWalker.StackFrame>, ? extends T> function)`
  Applies the given function to the stream of `StackFrame`s for the current thread, traversing from the top frame of the stack, which is the method calling this `walk` method.

  ### Methods declared in class Object

  `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- ## Method Details

  - ### getInstance

    public static StackWalker getInstance()
    Returns a `StackWalker` instance.

    This `StackWalker` is configured to skip all hidden frames and no class reference is retained.

    Returns:
      a `StackWalker` configured to skip all hidden frames and no class reference is retained.

  - ### getInstance

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

  - ### getInstance

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

    If the given `options` is empty, this `StackWalker` is configured to skip all hidden frames and no class reference is retained.

    Parameters:
      `options` - `stack walking options`
    Returns:
      a `StackWalker` configured with the given options

  - ### getInstance

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

    If the given `options` is empty, this `StackWalker` is configured to skip all hidden frames and no class reference is retained.

    The `estimateDepth` specifies the estimate number of stack frames this `StackWalker` will traverse that the `StackWalker` could use as a hint for the buffer size.

    Parameters:
      `options` - `stack walking options`
      `estimateDepth` - Estimate number of stack frames to be traversed.
    Returns:
      a `StackWalker` configured with the given options
    Throws:
      `IllegalArgumentException` - if `estimateDepth <= 0`

  - ### walk

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

    The `StackFrame` stream will be closed when this method returns. When a closed `Stream<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 package `com.foo`:

          List<StackFrame> frames = StackWalker.getInstance().walk(s ->
                  s.dropWhile(f -> f.getClassName().startsWith("com.foo."))
                   .limit(10)
                   .toList());

      This method takes a `Function` accepting a `Stream<StackFrame>`, rather than returning a `Stream<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 a `Function` 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 of stack frame.
    Parameters:
      `function` - a function that takes a stream of stack frames and returns a result.
    Returns:
      the result of applying the function to the stream of stack frame.

  - ### forEach

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

    This method is equivalent to calling

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

    Parameters:
      `action` - an action to be performed on each `StackFrame` of the stack of the current thread

  - ### getCallerClass

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

    This method filters reflection frames, `MethodHandle`, and hidden frames regardless of the `SHOW_REFLECT_FRAMES` and `SHOW_HIDDEN_FRAMES` options this `StackWalker` 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 throws `UnsupportedOperationException` if this `StackWalker` is not configured with the `RETAIN_CLASS_REFERENCE` option.

    API Note:
      For example, `Util::getResourceBundle` loads a resource bundle on behalf of the caller. It invokes `getCallerClass` to identify the class whose method called `Util::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 is `MyTool`.

          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 the `walk` 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 the `getCallerClass` method is called from a method that is the bottom most frame on the stack, for example, `static public void main` method launched by the `java` 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 this `StackWalker` is not configured with `Option.RETAIN_CLASS_REFERENCE`.
      `IllegalCallerException` - if there is no caller frame, i.e. when this `getCallerClass` method is called from a method which is the last frame on the stack.