Module  java.base
软件包  java.lang

Class StackWalker



  • public final class StackWalker
    extends Object
    堆栈步行者。

    walk方法为当前线程打开StackFrame s的顺序流,然后应用给定的函数来StackFrame流。 流从堆栈生成到最底层的执行点的最上面的帧起按顺序报告堆栈帧元素。 StackFrame流程在walk方法返回时关闭。 如果尝试重新使用封闭流,则将抛出IllegalStateException

    所述stack walking options一个的StackWalker确定的信息StackFrame要返回的对象。 默认情况下,反射API和实现类的堆栈帧为hidden,StackFrame具有可用的类名称和方法名称,但不包括Class reference

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

    API Note:
    例子

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

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

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

       List<StackFrame> stack = StackWalker.getInstance().walk(s -> s.limit(10).collect(Collectors.toList()));  
    除非另有说明,否则将null参数传递给此StackWalker类中的构造函数或方法将导致抛出NullPointerException
    从以下版本开始:
    9
    • 方法详细信息

      • getInstance

        public static StackWalker getInstance​(Set<StackWalker.Option> options,
                                              int estimateDepth)
        返回一个StackWalker实例,给定的options指定可以访问的堆栈帧信息。 如果给定的options为空,则此StackWalker配置为跳过所有hidden frames,并且不保留class reference

        如果存在安全管理员,并且给定的options包含Option.RETAIN_CLASS_REFERENCE ,则它将其checkPermission方法RuntimePermission("getStackWalkerWithClassReference")

        estimateDepth指定StackWalker将通过StackWalker可用作缓冲区大小提示的堆栈帧的估计数。

        参数
        options - stack walking options
        estimateDepth - 估计要运行的堆栈帧数。
        结果
        一个 StackWalker配置了给定的选项
        异常
        IllegalArgumentException - 如果是 estimateDepth <= 0
        SecurityException - 如果安全管理器存在,并且其 checkPermission方法拒绝访问。
      • walk

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

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

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

        该方法需要Function接受Stream<StackFrame> ,而不是返回一个Stream<StackFrame>并允许调用者直接操纵流。 Java虚拟机可以自由地重组线程的控制堆栈,例如通过去优化。 通过获取一个Function参数,该方法允许通过线程的控制堆栈的稳定视图访问堆栈帧。

        有效地禁止并行执行,流管道执行只会在当前线程上发生。

        Implementation Note:
        该实现通过锚定特定于堆栈行走的框架来稳定堆栈,并确保在锚定框架上执行堆栈行走。 当流对象关闭或重新使用时,将抛出IllegalStateException
        参数类型
        T - 将函数应用于流的结果的类型stack frame
        参数
        function - 一个接收stack frames流并返回结果的函数。
        结果
        将功能应用于stack frame的流的结果
      • forEach

        public void forEach​(Consumer<? super StackWalker.StackFrame> action)
        对当前线程的StackFrame流的每个元素执行给定的动作,从堆栈的顶部框架遍历,这是调用这个forEach方法的方法。

        这个方法相当于调用

        walk(s -> { s.forEach(action); return null; });
        参数
        action - 当前线程的堆栈中每个 StackFrame执行的操作
      • getCallerClass

        public Class<?> getCallerClass​()
        获取调用者调用getCallerClass的方法的调用者的Class对象。

        该方法过滤reflection framesMethodHandle ,和hidden frames不管SHOW_REFLECT_FRAMESSHOW_HIDDEN_FRAMES这个选项StackWalker已配置。

        当调用者帧存在时,应该调用此方法。 如果从堆栈的最底层调用,将抛出IllegalCallerException

        如果此StackWalker未配置RETAIN_CLASS_REFERENCE选项,则此方法将抛出UnsupportedOperationException

        API Note:
        例如, Util::getResourceBundle代表调用者加载资源束。 它调用getCallerClass来标识其方法叫做Util::getResourceBundle的类。 然后,它获取该类的类加载器,并使用类加载器加载资源束。 此示例中的调用者类为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"); } }  
        使用walk方法查找呼叫者类的方法如下(过滤反射帧, MethodHandle和隐藏帧,如下所示):
           Optional<Class<?>> caller = walker.walk(s -> s.map(StackFrame::getDeclaringClass) .skip(2) .findFirst());  
        getCallerClass方法是从在堆叠的底部最帧的方法调用,例如, static public void main方法由推出java发射器,或从JNI附线程上调用的方法, IllegalCallerException被抛出。
        结果
        调用方调用此方法的对象为 Class
        异常
        UnsupportedOperationException - 如果这个 StackWalker没有配置 Option.RETAIN_CLASS_REFERENCE
        IllegalCallerException - 如果没有调用方框,即当从堆栈中最后一帧的方法调用此 getCallerClass方法时。