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
-
Nested Class Summary
Modifier and TypeClassDescriptionstatic enum
配置StackWalker
获取的StackFrame
信息的堆栈行走器选项。static interface
StackFrame
对象表示由StackWalker
返回的方法调用。 -
Method Summary
Modifier and TypeMethodDescriptionvoid
forEach
(Consumer<? super StackWalker.StackFrame> action) 对当前线程的StackFrame
流的每个元素执行给定操作,从堆栈的顶部帧开始遍历,即调用此forEach
方法的方法。Class
<?> 获取调用者调用调用getCallerClass
方法的方法的Class
对象。static StackWalker
返回一个StackWalker
实例。static StackWalker
getInstance
(StackWalker.Option option) 返回具有指定堆栈帧信息访问权限的StackWalker
实例。static StackWalker
getInstance
(Set<StackWalker.Option> options) 返回具有指定堆栈帧信息访问权限的StackWalker
实例。static StackWalker
getInstance
(Set<StackWalker.Option> options, int estimateDepth) 返回具有指定堆栈帧信息访问权限的StackWalker
实例。<T> T
walk
(Function<? super Stream<StackWalker.StackFrame>, ? extends T> function) 将给定函数应用于当前线程的StackFrame
流,从堆栈的顶部帧开始遍历,即调用此walk
方法的方法。
-
Method Details
-
getInstance
返回一个StackWalker
实例。此
StackWalker
配置为跳过所有hidden frames
,不保留class reference
。- 返回:
-
配置为跳过所有
hidden frames
,不保留class reference
的StackWalker
。
-
getInstance
返回具有指定堆栈帧信息访问权限的StackWalker
实例。如果存在安全管理器并且给定的
option
是Option.RETAIN_CLASS_REFERENCE
,则调用其checkPermission
方法以获取RuntimePermission("getStackWalkerWithClassReference")
。- 参数:
-
option
-堆栈行走选项
- 返回:
-
配置为具有给定选项的
StackWalker
- 抛出:
-
SecurityException
- 如果存在安全管理器并且其checkPermission
方法拒绝访问。
-
getInstance
返回具有指定堆栈帧信息访问权限的StackWalker
实例。如果给定的
options
为空,则此StackWalker
配置为跳过所有hidden frames
,不保留class reference
。如果存在安全管理器并且给定的
options
包含Option.RETAIN_CLASS_REFERENCE
,则调用其checkPermission
方法以获取RuntimePermission("getStackWalkerWithClassReference")
。- 参数:
-
options
-堆栈行走选项
- 返回:
-
配置为具有给定选项的
StackWalker
- 抛出:
-
SecurityException
- 如果存在安全管理器并且其checkPermission
方法拒绝访问。
-
getInstance
返回具有指定堆栈帧信息访问权限的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
将给定函数应用于当前线程的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
对当前线程的StackFrame
流的每个元素执行给定操作,从堆栈的顶部帧开始遍历,即调用此forEach
方法的方法。此方法等效于调用
walk(s -> { s.forEach(action); return null; });
- 参数:
-
action
- 要对当前线程的堆栈的每个StackFrame
执行的操作
-
getCallerClass
Gets theClass
object of the caller who invoked the method that invokedgetCallerClass
.This method filters reflection frames,
MethodHandle
, and hidden frames regardless of theSHOW_REFLECT_FRAMES
andSHOW_HIDDEN_FRAMES
options thisStackWalker
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 thisStackWalker
is not configured with theRETAIN_CLASS_REFERENCE
option.- API Note:
-
For example,
Util::getResourceBundle
loads a resource bundle on behalf of the caller. It invokesgetCallerClass
to identify the class whose method calledUtil::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 isMyTool
.
An equivalent way to find the caller class using theclass 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
method is as follows (filtering the reflection frames,MethodHandle
and hidden frames not shown below):
When theOptional<Class<?>> caller = walker.walk(s -> s.map(StackFrame::getDeclaringClass) .skip(2) .findFirst());
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 thejava
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 thisStackWalker
is not configured withOption.RETAIN_CLASS_REFERENCE
. -
IllegalCallerException
- if there is no caller frame, i.e. when thisgetCallerClass
method is called from a method which is the last frame on the stack.
-