How do I get the current stack trace in Java, like how in .NET you can do Environment.StackTrace
?
I found Thread.dumpStack()
but it is not what I want - I want to get the stack trace back, not print it out.
You can use Thread.currentThread().getStackTrace()
.
That returns an array of StackTraceElement
s that represent the current stack trace of a program.
StackTraceElement[] st = Thread.currentThread().getStackTrace();
is fine if you don't care what the first element of the stack is.
StackTraceElement[] st = new Throwable().getStackTrace();
will have a defined position for your current method, if that matters.
(new Throwable()).getStackTrace()
is faster executing too (see bugs.sun.com/bugdatabase/view_bug.do?bug_id=6375302 )
(new Exception()).getStackTrace()
when the requested stack trace is on the current thread (which will always be the case for Thread.currentThread().getStackTrace();
for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
System.out.println(ste);
}
new Exception().printStackTrace(System.out)
which I can remember, the for loop probably has less overhead, but you should only use this as a debugging thing anyway...
for (StackTraceElement ste : Thread.currentThread().getStackTrace()) { if(ste.toString().contains("mypackages")){ System.out.println(ste); } }
Thread.currentThread().getStackTrace();
is available since JDK1.5.
For an older version, you can redirect exception.printStackTrace()
to a StringWriter()
:
StringWriter sw = new StringWriter();
new Throwable("").printStackTrace(new PrintWriter(sw));
String stackTrace = sw.toString();
new Throwable().getStackTrace()
is available since JDK1.4…
Tony, as a comment to the accepted answer, has given what seems to be the best answer which actually answers the OP's question:
Arrays.toString(Thread.currentThread().getStackTrace()).replace( ',', '\n' );
... the OP did NOT ask how to get a String
from the stack trace from an Exception
. And although I'm a huge fan of Apache Commons, when there is something as simple as the above there is no logical reason to use an outside library.
Thread.getAllStackTraces()
which gives you a Map<Thread, StackTraceElement[]>
. Hotspot will safepoint all threads whenever it needs to safepoint one. Zing can bring individual threads to a safepoint without disturbing the other. Getting a stacktrace requires a safepoint. Thread.getAllStackTraces()
gets all stack traces and stops all threads only once. Of course, you must find out which mapping you are actually interested in.
You can use Apache's commons for that:
String fullStackTrace = org.apache.commons.lang3.exception.ExceptionUtils.getStackTrace(e);
org.apache.commons.lang3
, the full line is: org.apache.commons.lang3.exception.ExceptionUtils.getStackTrace(e);
org.apache.commons.lang3
, which I initially overlooked -- the import uses lang3
instead of lang
, and replaces getFullStackTrace
with getStackTrace
.
ExceptionUtils.getStackTrace(new Throwable())
expression to get the stack trace.
On android a far easier way is to use this:
import android.util.Log;
String stackTrace = Log.getStackTraceString(exception);
Another solution (only 35 31 characters):
new Exception().printStackTrace();
new Error().printStackTrace();
To get the stack trace of all threads you can either use the jstack utility, JConsole or send a kill -quit signal (on a Posix operating system).
However, if you want to do this programmatically you could try using ThreadMXBean:
ThreadMXBean bean = ManagementFactory.getThreadMXBean();
ThreadInfo[] infos = bean.dumpAllThreads(true, true);
for (ThreadInfo info : infos) {
StackTraceElement[] elems = info.getStackTrace();
// Print out elements, etc.
}
As mentioned, if you only want the stack trace of the current thread it's a lot easier - Just use Thread.currentThread().getStackTrace()
;
System.err.println(elems[i])
on each). The second line in the snippet is missing bean.
before the dumpAllThreads
but I guess most people could work that out.
Silly me, it's Thread.currentThread().getStackTrace();
In Java 9 there is a new way:
public static void showTrace() {
List<StackFrame> frames =
StackWalker.getInstance( Option.RETAIN_CLASS_REFERENCE )
.walk( stream -> stream.collect( Collectors.toList() ) );
for ( StackFrame stackFrame : frames )
System.out.println( stackFrame );
}
Getting stacktrace:
StackTraceElement[] ste = Thread.currentThread().getStackTrace();
Printing stacktrace (JAVA 8+):
Arrays.asList(ste).forEach(System.out::println);
Printing stacktrage (JAVA 7):
StringBuilder sb = new StringBuilder();
for (StackTraceElement st : ste) {
sb.append(st.toString() + System.lineSeparator());
}
System.out.println(sb);
I suggest that
Thread.dumpStack()
is an easier way and has the advantage of not actually constructing an exception or throwable when there may not be a problem at all, and is considerably more to the point.
new Exception("Stack trace").printStackTrace();
so it's actually building a Throwable
To string with guava:
Throwables.getStackTraceAsString(new Throwable())
I have a utility method that returns a string with the stacktrace:
static String getStackTrace(Throwable t) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw, true);
t.printStackTrace(pw);
pw.flush();
sw.flush();
return sw.toString();
}
And just logit like...
...
catch (FileNotFoundException e) {
logger.config(getStackTrace(e));
}
java.util.logging.Logger#log(Level, String, Throwable)
already does this. This is rewriting things that already exist in the Java standard library unnecessarily and is pointing new developers in the wrong direction, which is away from the documentation. By doing this now you have forced the Stacktrace to be formatted a certain way, where as the logging
API allows you to vary formatting of the log statement dynamically as you specify it. To my knowledge, log4j
also has similar behavior as well. Don't reinvent the wheel because you end up losing things such as I have explained.
Throwable
off to the Handler
s through to the Formatter
s in 2012 which was Java7, more than I've listed here. And these functions date back far longer than Java7 has been around; hence J2SE 5.0 javadocs)
try {
}
catch(Exception e) {
StackTraceElement[] traceElements = e.getStackTrace();
//...
}
or
Thread.currentThread().getStackTrace()
Maybe you could try this:
catch(Exception e)
{
StringWriter writer = new StringWriter();
PrintWriter pw = new PrintWriter(writer);
e.printStackTrace(pw);
String errorDetail = writer.toString();
}
The string 'errorDetail' contains the stacktrace.
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
The last element of the array represents the bottom of the stack, which is the least recent method invocation in the sequence.
A StackTraceElement has getClassName(), getFileName(), getLineNumber() and getMethodName().
loop through StackTraceElement and get your desired result.
for (StackTraceElement ste : stackTraceElements )
{
//do your stuff here...
}
You can use jstack utility if you want to check the current call stack of your process.
Usage:
jstack [-l] <pid>
(to connect to running process)
jstack -F [-m] [-l] <pid>
(to connect to a hung process)
jstack [-m] [-l] <executable> <core>
(to connect to a core file)
jstack [-m] [-l] [server_id@]<remote server IP or hostname>
(to connect to a remote debug server)
Options:
-F to force a thread dump. Use when jstack <pid> does not respond (process is hung)
-m to print both java and native frames (mixed mode)
-l long listing. Prints additional information about locks
-h or -help to print this help message
I used answers from above and added formatting
public final class DebugUtil {
private static final String SEPARATOR = "\n";
private DebugUtil() {
}
public static String formatStackTrace(StackTraceElement[] stackTrace) {
StringBuilder buffer = new StringBuilder();
for (StackTraceElement element : stackTrace) {
buffer.append(element).append(SEPARATOR);
}
return buffer.toString();
}
public static String formatCurrentStacktrace() {
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
return formatStackTrace(stackTrace);
}
}
For people, who just want to get the current stacktrace to their logs, I would go with:
getLogger().debug("Message", new Throwable());
Cheers
This is an old post, but here is my solution :
Thread.currentThread().dumpStack();
More info and more methods there : http://javarevisited.blogspot.fr/2013/04/how-to-get-current-stack-trace-in-java-thread.html
Thread.dumpStack()
directly because its static method.
Success story sharing
String fullStackTrace = org.apache.commons.lang.exception.ExceptionUtils.getFullStackTrace(e);
stackoverflow.com/a/10620951/11236new Throwable().getStackTrace()
is much faster, because it doesn't need to checkthis != Thread.currentThread()
and bypasses potential JVM overheads of calling it through child-class (Exception extends Throwable
)