In this post, we will be covering StackWalker API in Java 9. Stack Walking API is yet another features being introduced in Java 9
To put Stack Walk API in Java 9 in simple words, It provides capabilities to walk through the stack in Java. StackWalker provides a snapshot of the current thread stack trace along with some methods to access it.
Before Java 9, There was no standard / efficient way to access selected frames of the stack and get information about the Class instance of each frame. We have the following options available to get information from the Stack Trace
getStackTrace()
method from java.lang.Throwable
Class which returns an array of StackTraceElement.
So if you want to get information about the stack trace before Java 9, a simpler code will look similar to
StackTraceElement[] stackTrace = new Throwable().getStackTrace();
Above method require JVM to capture the snapshot of the entire stack and return this information back to the calling method / API. This is not a very efficient solution due to following use cases.
Class
instance.Thread.getStackTrace()
method.If you want you can use java.lang.SecurityManager.getClassContext()
method to get access to the Class instance but I will not be covering that part in this post.
One of natural question which comes to our mind is why do we need StackWalker API in Java 9? Here are some of the benefits which you will be getting from this new API.
java.lang.SecurityManager.getClassContext()
method.
Let’s cover some of the basic of the StackWalker API along with details as to how we can use it in future.StackWalker class is easy to use and provide some convenient method to work on the stack.
StackWalker API provides a static getInstance method which can be used to obtained StackWalker instance.
StackWalker stackWalker = StackWalker.getInstance();
There are other variants of the getInstance()
method which can be used based on the individual requirements.
Let’s start building our example to demonstrate various features of the StackWalker API in Java 9.
Here is our sample class with some method creating method chain.
package com.umeshawasthi.java9.example.stackwalker;
public class StackWalkerExample {
public static void stackWalkerMethod1() {
stackWalkerMethod1();
}
public static void stackWalkerMethod2() {
stackWalkerMethod2();
}
public static void stackWalkerMethod3() {
stackWalkerMethod3();
}
public static void stackWalkerMethod4() {
mainWalkerMethod();
}
public static void printCompleteStackTrace() {
}
}
In order to get the complete stack, we will get an instance of the StackWalker and will use walk method to opens a sequential stream.
public static void printCompleteStackTrace() {
List<StackWalker.StackFrame> stack = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE)
.walk((s) -> s.collect(Collectors.toList()));
stack.forEach(System.out::println);
}
In above method we get an instance of the StackWalker and use the walk method opens a sequential stream of StackFrames for the current thread.
Here is the output of the above method.
java/com.umeshawasthi.java9.example.stackwalker.StackWalkerExample.printCompleteStackTrace(StackWalkerExample.java:39)
java/com.umeshawasthi.java9.example.stackwalker.StackWalkerExample.stackWalkerMethod3(StackWalkerExample.java:28)
java/com.umeshawasthi.java9.example.stackwalker.StackWalkerExample.stackWalkerMethod2(StackWalkerExample.java:23)
java/com.umeshawasthi.java9.example.stackwalker.StackWalkerExample.stackWalkerMethod1(StackWalkerExample.java:18)
java/com.umeshawasthi.java9.example.stackwalker.StackWalkerExample.main(StackWalkerExample.java:13)
Let’s say we are only interested in a stack from a specific class, to achieve this we do not have to go through each and every frame. StackWalker API provides a convenient option to filter out results which are of our interest.
public void filterStackFrame() {
List<StackWalker.StackFrame> filterFrames = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE)
.walk((s) -> s.filter(f -> f.getClassName().contains(StackWalkerDemo3.class.getName()))
.collect(Collectors.toList()));
filterFrames.forEach(System.out::println);
}
As we saw in above example, We are only interested in the StackFrame from the StackWalkerDemo3 class, so we passed it as a filter and StackWalker API will filter out it for us. Below is the output of the above code
java/com.umeshawasthi.java9.example.stackwalker.StackWalkerFilterExample$StackWalkerDemo3.stackWalkerMethod3(StackWalkerFilterExample.java:35)
StackWalker API provides a way to show all reflection and hidden Frames which are hidden by default. StackWalker configured with this SHOW_REFLECT_FRAMES option will show all reflection frames, a similar way we can use SHOW_HIDDEN_FRAMES to show all hidden frames.
public static void printCompleteStackTrace() {
List<StackWalker.StackFrame> stack = StackWalker.getInstance(StackWalker.Option.SHOW_REFLECT_FRAMES)
.walk((s) -> s.collect(Collectors.toList()));
stack.forEach(System.out::println);
}
Let’s say we just want the top 3 stack frames from the current thread, we can use limit option for achieving this.
List<StackWalker.StackFrame> stack = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE)
.walk((s) ->s.limit(3).collect(Collectors.toList()));
We discussed in the starting of this post that StackWalker API provides a way to get hold of the calling class Instance which was not possible before Java 9 (We do have some indirect way). To get hold of the calling class instance you need RETAIN_CLASS_REFERENCE
while getting StackWalker instance.
RETAIN_CLASS_REFERENCE
will retain an instance of all classes walked by StackWalker, we can use getCallerClass and getDeclaringClass method to get hold of the class instance.
public static void getCallerClass() {
Class calledClass = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE)
.getCallerClass();
System.out.println("Caller Class is " +calledClass.getCanonicalName());
}
Output of above program is
Caller Class is com.umeshawasthi.java9.example.stackwalker.StackWalkerGetClass
In this post, we explore StackWalker API being introduced in Java 9. We checked how we can get stack based on our requirement with an option to filter or limit results along with the ability to display hidden frames. We explored possibility to get hold of the calling Class instance using Java 9 StackWalker API
If you are interested in learning other features being introduced in Java 9, Please read following posts on Java 9
Collection Factory Methods in Java 9
All the code of this article is available Over on Github. This is a Maven-based project.
References
Hello!! Welcome to the Java Development Journal. We love to share our knowledge with our readers and love to build a thriving community.