StackWalker (Java SE 12 & JDK 12 )
Keywords: java.lang.StackWalker class

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 class` | `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 Detail

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