Class StackWalker
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.
Stack walker options configure the stack frame
information obtained by a StackWalker
.
By default, the class name and method information are collected but
not the Class reference
.
The method information can be dropped via the DROP_METHOD_INFO
option. The Class
object can be retained for
access via the RETAIN_CLASS_REFERENCE
option.
Stack frames of the reflection API and implementation classes are
hidden by default.
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 out a known list of implementation class:
StackWalker walker = StackWalker.getInstance(Set.of(Option.DROP_METHOD_INFO, Option.RETAIN_CLASS_REFERENCE)); Optional<Class<?>> callerClass = walker.walk(s -> s.map(StackFrame::getDeclaringClass) .filter(Predicate.not(implClasses::contains)) .findFirst());
2. To snapshot the top 10 stack frames of the current thread,
List<StackFrame> stack = StackWalker.getInstance().walk(s -> s.limit(10).toList());
null
argument to a constructor or method in thisStackWalker
class will cause aNullPointerException
to be thrown. - Since:
- 9
-
Nested Class Summary
Modifier and TypeClassDescriptionstatic enum
Stack walker option to configure the stack frame information obtained by aStackWalker
.static interface
AStackFrame
object represents a method invocation returned byStackWalker
. -
Method Summary
Modifier and TypeMethodDescriptionvoid
forEach
(Consumer<? super StackWalker.StackFrame> action) Performs the given action on each element ofStackFrame
stream of the current thread, traversing from the top frame of the stack, which is the method calling thisforEach
method.Class
<?> Gets theClass
object of the caller who invoked the method that invokedgetCallerClass
.static StackWalker
Returns aStackWalker
instance.static StackWalker
getInstance
(StackWalker.Option option) Returns aStackWalker
instance with the given option specifying the stack frame information it can access.static StackWalker
getInstance
(Set<StackWalker.Option> options) Returns aStackWalker
instance with the givenoptions
specifying the stack frame information it can access.static StackWalker
getInstance
(Set<StackWalker.Option> options, int estimateDepth) Returns aStackWalker
instance with the givenoptions
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 ofStackFrame
s for the current thread, traversing from the top frame of the stack, which is the method calling thiswalk
method.
-
Method Details
-
getInstance
Returns aStackWalker
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
Returns aStackWalker
instance with the given option specifying the stack frame information it can access.If a security manager is present and the given
option
isOption.RETAIN_CLASS_REFERENCE
, it calls itscheckPermission
method forRuntimePermission("getStackWalkerWithClassReference")
.- Parameters:
option
-stack walking option
- Returns:
- a
StackWalker
configured with the given option - Throws:
SecurityException
- if a security manager exists and itscheckPermission
method denies access.
-
getInstance
Returns aStackWalker
instance with the givenoptions
specifying the stack frame information it can access.If the given
options
is empty, thisStackWalker
is configured to skip all hidden frames and no class reference is retained.If a security manager is present and the given
options
containsOption.RETAIN_CLASS_REFERENCE
, it calls itscheckPermission
method forRuntimePermission("getStackWalkerWithClassReference")
.- Parameters:
options
-stack walking options
- Returns:
- a
StackWalker
configured with the given options - Throws:
SecurityException
- if a security manager exists and itscheckPermission
method denies access.
-
getInstance
Returns aStackWalker
instance with the givenoptions
specifying the stack frame information it can access.If the given
options
is empty, thisStackWalker
is configured to skip all hidden frames and no class reference is retained.If a security manager is present and the given
options
containsOption.RETAIN_CLASS_REFERENCE
, it calls itscheckPermission
method forRuntimePermission("getStackWalkerWithClassReference")
.The
estimateDepth
specifies the estimate number of stack frames thisStackWalker
will traverse that theStackWalker
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
- ifestimateDepth <= 0
SecurityException
- if a security manager exists and itscheckPermission
method denies access.
-
walk
Applies the given function to the stream ofStackFrame
s for the current thread, traversing from the top frame of the stack, which is the method calling thiswalk
method.The
StackFrame
stream will be closed when this method returns. When a closedStream<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) .toList());
This method takes a
Function
accepting aStream<StackFrame>
, rather than returning aStream<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 aFunction
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
Performs the given action on each element ofStackFrame
stream of the current thread, traversing from the top frame of the stack, which is the method calling thisforEach
method.This method is equivalent to calling
walk(s -> { s.forEach(action); return null; });
- Parameters:
action
- an action to be performed on eachStackFrame
of the stack of the current thread
-
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
.class Util { private final StackWalker walker = StackWalker.getInstance(Set.of(Option.DROP_METHOD_INFO, 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):Optional<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.
-