Module java.base
Package java.lang

Class StackWalker

java.lang.Object
java.lang.StackWalker

public final class StackWalker extends Object
一个堆栈行走器。

walk 方法打开当前线程的StackFrame的顺序流,然后应用给定的函数来遍历StackFrame流。该流按顺序报告堆栈帧元素,从表示生成堆栈的执行点的最顶部帧到最底部帧。当walk方法返回时,StackFrame流将被关闭。如果尝试重用已关闭的流,则会抛出IllegalStateException异常。

StackWalker是线程安全的。多个线程可以共享单个StackWalker对象来遍历自己的堆栈。创建StackWalker时会执行权限检查,根据请求的选项进行。在堆栈遍历时不会进行进一步的权限检查。

API 注意:
示例

1. 查找第一个调用者,过滤已知的实现类列表:


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

2. 快照当前线程的前10个堆栈帧,


     List<StackFrame> stack = StackWalker.getInstance().walk(s ->
         s.limit(10).collect(Collectors.toList()));
 
除非另有说明,在StackWalker类中向构造函数或方法传递null参数将导致抛出NullPointerException异常。
自 JDK 版本:
9
  • Method Details

    • getInstance

      public static StackWalker getInstance()
      返回一个StackWalker实例。

      StackWalker配置为跳过所有hidden frames,不保留class reference

      返回:
      配置为跳过所有hidden frames,不保留class referenceStackWalker
    • getInstance

      public static StackWalker getInstance(StackWalker.Option option)
      返回具有指定堆栈帧信息访问权限的StackWalker实例。

      如果存在安全管理器并且给定的optionOption.RETAIN_CLASS_REFERENCE,则调用其checkPermission方法以获取RuntimePermission("getStackWalkerWithClassReference")

      参数:
      option - 堆栈行走选项
      返回:
      配置为具有给定选项的StackWalker
      抛出:
      SecurityException - 如果存在安全管理器并且其checkPermission方法拒绝访问。
    • getInstance

      public static StackWalker getInstance(Set<StackWalker.Option> options)
      返回具有指定堆栈帧信息访问权限的StackWalker实例。

      如果给定的options为空,则此StackWalker配置为跳过所有hidden frames,不保留class reference

      如果存在安全管理器并且给定的options包含Option.RETAIN_CLASS_REFERENCE,则调用其checkPermission方法以获取RuntimePermission("getStackWalkerWithClassReference")

      参数:
      options - 堆栈行走选项
      返回:
      配置为具有给定选项的StackWalker
      抛出:
      SecurityException - 如果存在安全管理器并且其checkPermission方法拒绝访问。
    • getInstance

      public static StackWalker getInstance(Set<StackWalker.Option> options, int estimateDepth)
      返回具有指定堆栈帧信息访问权限的StackWalker实例。

      如果给定的options为空,则此StackWalker配置为跳过所有hidden frames,不保留class reference

      如果存在安全管理器并且给定的options包含Option.RETAIN_CLASS_REFERENCE,则调用其checkPermission方法以获取RuntimePermission("getStackWalkerWithClassReference")

      estimateDepth指定此StackWalker将遍历的堆栈帧的估计数量,StackWalker可以将其用作缓冲区大小的提示。

      参数:
      options - 堆栈行走选项
      estimateDepth - 要遍历的堆栈帧的估计数量。
      返回:
      配置为具有给定选项的StackWalker
      抛出:
      IllegalArgumentException - 如果estimateDepth <= 0
      SecurityException - 如果存在安全管理器并且其checkPermission方法拒绝访问。
    • walk

      public <T> T walk(Function<? super Stream<StackWalker.StackFrame>,? extends T> function)
      将给定函数应用于当前线程的StackFrame流,从堆栈的顶部帧开始遍历,即调用此walk方法的方法。

      当此方法返回时,StackFrame流将被关闭。当尝试重用已关闭的Stream<StackFrame>对象时,将抛出IllegalStateException异常。

      API 注意:
      例如,要查找前10个调用帧,首先跳过那些声明类在包com.foo中的帧:
      
       List<StackFrame> frames = StackWalker.getInstance().walk(s ->
           s.dropWhile(f -> f.getClassName().startsWith("com.foo."))
            .limit(10)
            .collect(Collectors.toList()));
       

      此方法接受一个接受Stream<StackFrame>Function,而不是返回Stream<StackFrame>并允许调用者直接操作流。Java虚拟机可以通过去优化等方式重新组织线程的控制堆栈。通过接受Function参数,此方法允许通过线程的控制堆栈的稳定视图访问堆栈帧。

      并行执行被有效地禁用,流管道执行将仅在当前线程上发生。

      实现注意:
      该实现通过锚定特定于堆栈行走的帧来稳定堆栈,并确保在锚定帧之上执行堆栈行走。当流对象关闭或被重用时,将抛出IllegalStateException异常。
      类型参数:
      T - 将函数应用于StackFrame流的结果的类型。
      参数:
      function - 一个接受StackFrame流的函数,并返回结果。
      返回:
      将函数应用于StackFrame流的结果。
    • forEach

      public void forEach(Consumer<? super StackWalker.StackFrame> action)
      对当前线程的StackFrame流的每个元素执行给定操作,从堆栈的顶部帧开始遍历,即调用此forEach方法的方法。

      此方法等效于调用

      walk(s -> { s.forEach(action); return null; });
      参数:
      action - 要对当前线程的堆栈的每个StackFrame执行的操作
    • 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.