Module java.base
Package java.lang

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

The stack walking options of a `StackWalker` determines the information of `StackFrame` objects to be returned. By default, stack frames of the reflection API and implementation classes are hidden and `StackFrame`s have the class name and method name available but not the `Class reference`.

`StackWalker` is thread-safe. Multiple threads can share a single `StackWalker` object to traverse its own stack. A permission check is performed when a `StackWalker` is created, according to the options it requests. No further permission check is done at stack walking time.

API Note:
  Examples

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

           StackWalker walker = StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE);
           Optional<Class<?>> callerClass = walker.walk(s ->
               s.map(StackFrame::getDeclaringClass)
                .filter(interestingClasses::contains)
                .findFirst());

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

           List<StackFrame> stack = StackWalker.getInstance().walk(s ->
               s.limit(10).collect(Collectors.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 java.lang.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.

    If a security manager is present and the given `option` is `Option.RETAIN_CLASS_REFERENCE`, it calls its `checkPermission` method for `RuntimePermission("getStackWalkerWithClassReference")`.

    Parameters:
      `option` - `stack walking option`
    Returns:
      a `StackWalker` configured with the given option
    Throws:
      `SecurityException` - if a security manager exists and its `checkPermission` method denies access.

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

    If a security manager is present and the given `options` contains `Option.RETAIN_CLASS_REFERENCE`, it calls its `checkPermission` method for `RuntimePermission("getStackWalkerWithClassReference")`.

    Parameters:
      `options` - `stack walking option`
    Returns:
      a `StackWalker` configured with the given options
    Throws:
      `SecurityException` - if a security manager exists and its `checkPermission` method denies access.

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

    If a security manager is present and the given `options` contains `Option.RETAIN_CLASS_REFERENCE`, it calls its `checkPermission` method for `RuntimePermission("getStackWalkerWithClassReference")`.

    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`
      `SecurityException` - if a security manager exists and its `checkPermission` method denies access.

  - ### 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)
      >           .collect(Collectors.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(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.