# 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`
Modifier and Type
Method
Description
`protected Object`
`clone()`
Creates and returns a copy of this object.
`boolean`
`equals(Object obj)`
Indicates whether some other object is "equal to" this one.
`protected void`
`finalize()`
Deprecated, for removal: This API element is subject to removal in a future version.
Finalization is deprecated and subject to removal in a future release.
`final Class<?>`
`getClass()`
Returns the runtime class of this `Object`.
`int`
`hashCode()`
Returns a hash code value for this object.
`final void`
`notify()`
Wakes up a single thread that is waiting on this object's monitor.
`final void`
`notifyAll()`
Wakes up all threads that are waiting on this object's monitor.
`String`
`toString()`
Returns a string representation of the object.
`final void`
`wait()`
Causes the current thread to wait until it is awakened, typically by being notified or interrupted.
`final void`
`wait(long timeoutMillis)`
Causes the current thread to wait until it is awakened, typically by being notified or interrupted, or until a certain amount of real time has elapsed.
`final void`
`wait(long timeoutMillis, int nanos)`
Causes the current thread to wait until it is awakened, typically by being notified or interrupted, or until a certain amount of real time has elapsed.

## 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.