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.