1113

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.

Michael
  • 41,989
  • 11
  • 82
  • 128
ripper234
  • 222,824
  • 274
  • 634
  • 905
  • 78
    I allways use "new Exception().printStackTrace()" as a watch expression when I'm debugging in Eclipse. That's handy when you suspend at a breakpoint and want to know where you came from. – Tim Büthe Jul 01 '09 at 14:07
  • 24
    @TimBüthe: isn't Eclipse already telling you the Stack Trace when you are in debug mode? I think so. – Luigi Massa Gallerano Aug 09 '13 at 10:20
  • 49
    Arrays.toString(Thread.currentThread().getStackTrace()); simple enough. – Ajay Oct 23 '13 at 07:24
  • The question text asks about .Net but the tags name Java. Is this question about .Net or Java (or does it apply to both)? – Bobulous Sep 20 '14 at 14:05
  • 2
    @Arkanon It refers to java, and is showing how they would do it in .net and what the equivalent is in java. – Pokechu22 Oct 16 '14 at 15:43
  • 13
    To print it nicely you can use apache StringUtils: StringUtils.join(currentThread().getStackTrace(), "\n"); – Art Nov 14 '14 at 12:01
  • Luigi MG - We can not assume that they are in Eclipse or any other development environment. If they are, and can stop the program, then fine. But conversely, for example, it is often useful to put parts of stack traces in a service's log file for later problem diagnosis. – user1062589 Oct 01 '16 at 12:57

23 Answers23

1284

You can use Thread.currentThread().getStackTrace().

That returns an array of StackTraceElements that represent the current stack trace of a program.

David Newcomb
  • 10,639
  • 3
  • 49
  • 62
jjnguy
  • 136,852
  • 53
  • 295
  • 323
  • 52
    A cool one-liner if you're already using apache commons to get a string: `String fullStackTrace = org.apache.commons.lang.exception.ExceptionUtils.getFullStackTrace(e);` http://stackoverflow.com/a/10620951/11236 – ripper234 May 26 '13 at 12:50
  • 5
    The first element (index 0) in the array is the java.lang.Thread.getStackTrace method, the second (index 1) usually is the first of interest. – lilalinux Feb 05 '14 at 13:16
  • 228
    A one liner to convert the stack trace to a string that works when you don't have an exception and you aren't using Apache Arrays.toString(Thread.currentThread().getStackTrace()) – Tony Mar 17 '14 at 17:04
  • rare to see a 500 booty claimed – Srinath Ganesh May 05 '14 at 09:54
  • 10
    @Tony 's solution is better because it doesn't require a throwable – mvd Jan 26 '15 at 20:51
  • 8
    As pointed in many answers below - the `new Throwable().getStackTrace()` is much faster, because it doesn't need to check `this != Thread.currentThread()` and bypasses potential JVM overheads of calling it through child-class (`Exception extends Throwable`) – Vlad Apr 09 '15 at 17:01
  • But in this case it will return us the array how can we specifically get the class name from which that method has been called without traversing the whole array? – Harshit Gupta Jun 27 '15 at 10:10
  • Is there a property you set to the vm to be able to dump the stacktrace ? Rather than adding code, in case the code is not available to be modified – Bionix1441 Sep 02 '16 at 09:30
  • @ripper234 Thank you for your comment, it's pretty useful. I've noticed the comment has some weird layout characters causing a compile error when copy pasting. Could you edit? They are a zero width non joiner and a zero width space just after the first c in getFullStackTrace. (can be seen in the html source) – Sam Dec 21 '17 at 11:39
  • Running maven with junit on surefire, this does not work for me due to a SurefireBooterForkException (stack underflow). I create a static method in _a different_ class using `new Exception()` instead of `Thread.currentThread()` or `new Throwable()`: `public static StackTraceElement[] getStack() { return (new Exception()).getStackTrace(); }` – John Jul 23 '19 at 21:31
293
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.

JohnK
  • 6,865
  • 8
  • 49
  • 75
Yishai
  • 90,445
  • 31
  • 189
  • 263
  • 42
    `(new Throwable()).getStackTrace()` is faster executing too (see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6375302 ) – MightyE Aug 01 '12 at 20:38
  • 2
    Can you explain in more detail how the results of Thread.currentThread().getStackTrace() may be different from new Throwable().getStackTrace() ? I tried both and found that Thread.currentThread().getStackTrace() returns am array with Thread.getStackTrace in index 0 and the calling method is at index 1. The new Throwable().getStackTrace() method returns an array with the calling method at index 0. It seems like both methods have a defined position for the current method but the positions are different. Is there another difference you are pointing out? – Ryan Jun 06 '13 at 19:51
  • 9
    @Ryan, there is no guarantee that Thread.currentThread().getStackTrace() does not promise to maintain that position over different versions of the method. So when you happen to check it was at index 1. On some version of the JVM (1.5 or 1.6, don't remember) for Sun, it was index 2. That is what I mean by a defined position - the spec calls for it to be there, and stay there in the future. – Yishai Jun 09 '13 at 15:39
  • 5
    @MightyE The bug is now reported as closed as fixed in Java 6. Looking at the internals, it looks like it now does `(new Exception()).getStackTrace()` when the requested stack trace is on the current thread (which will always be the case for `Thread.currentThread().getStackTrace();` – M. Justin Jun 06 '17 at 20:44
  • 1
    @MightyE: the bug you have linked has been fixed six years before you wrote your comment. – Holger Oct 17 '17 at 13:38
  • 4
    @MJustin: the bug is not “now” reported as fixed, it has been fixed even six years before MightyE wrote the comment. In fact, it has been fixed even before Stackoverflow has been founded… – Holger Oct 17 '17 at 13:43
  • That's an awesome trick to debug a code :D. Worked perfectly! – Augusto Carmo Feb 26 '19 at 10:49
  • **The leading comment *\*is from 2006\**. See the other comments - the bug was fixed before this site was founded.** – i336_ Dec 20 '19 at 15:43
  • `new Exception()` is still a 20-30% faster to my tests on both recent JVM 1.8 and OpenJDK 11, so no reason to not use it really. I also find it more readable. – lapo Jun 17 '20 at 14:38
203
for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
    System.out.println(ste + "\n");
}
Leif Gruenwoldt
  • 13,561
  • 5
  • 60
  • 64
  • 23
    java has a printStackTrace method defined on Throwable, you can do: `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... – Jaap Nov 26 '13 at 10:28
  • 2
    I like this one best because you get a chance to strip out noise, by wrapping your println statement, e.g. `for (StackTraceElement ste : Thread.currentThread().getStackTrace()) { if(ste.toString().contains("mypackages")){ System.out.println(ste); } }` – nby Mar 24 '17 at 20:09
65
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();
jjnguy
  • 136,852
  • 53
  • 295
  • 323
RealHowTo
  • 34,977
  • 11
  • 70
  • 85
64

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.

mike rodent
  • 14,126
  • 11
  • 103
  • 157
  • I have a list of threads and I need to print their stack traces. – Daniil Iaitskov May 29 '17 at 11:53
  • In that case, make sure you use `Thread.getAllStackTraces()` which gives you a `Map`. 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. – Ralf H Nov 18 '17 at 19:42
42

You can use Apache's commons for that:

String fullStackTrace = org.apache.commons.lang3.exception.ExceptionUtils.getStackTrace(e);
stikkos
  • 1,916
  • 2
  • 19
  • 34
  • 13
    This is a nice one line solution. FYI, for anyone using `org.apache.commons.lang3`, the full line is: `org.apache.commons.lang3.exception.ExceptionUtils.getStackTrace(e);` – fileoffset Jul 26 '12 at 01:43
  • 2
    Just to reiterate fileoffset's comment when moving to `org.apache.commons.lang3`, which I initially overlooked -- the import uses `lang3` instead of `lang`, and replaces `getFullStackTrace` with `getStackTrace`. – ggkmath Jun 26 '13 at 15:00
  • That is very useful! When debugging using an IDE (for example, IntelliJ IDEA), it is great to use the `ExceptionUtils.getStackTrace(new Throwable())` expression to get the stack trace. – Sergey Vyacheslavovich Brunov Feb 21 '19 at 13:57
25

On android a far easier way is to use this:

import android.util.Log;
String stackTrace = Log.getStackTraceString(exception); 
Vicky Kapadia
  • 6,025
  • 2
  • 24
  • 30
24

Another solution (only 35 31 characters):

new Exception().printStackTrace();   
new Error().printStackTrace();
kukis
  • 4,489
  • 6
  • 27
  • 50
22

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();

Adamski
  • 54,009
  • 15
  • 113
  • 152
  • 2
    The code snippet in this answer comes nearest to programmatically generating the kind of dump you see on sending the JVM the QUIT signal (on Unix like systems) or on Windows. Unlike the other answers you get to see monitors and synchronizers as well as just the stack traces (e.g. if you iterate over the StackTraceElement array and do `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. – George Hawkins May 19 '11 at 08:01
18

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.

Thomas Adkins
  • 412
  • 3
  • 6
  • 1
    Okay, actually, the dumpStack() is a static method, and should be accessed in a static way. Thanks, eclipse! – Thomas Adkins Jul 18 '17 at 01:54
  • 5
    I love the shortcut, but the source code for this method is : `new Exception("Stack trace").printStackTrace();` so it's actually building a Throwable – Florent Mar 02 '18 at 14:11
  • 1
    The question was "I found Thread.dumpStack() but it is not what I want - I want to get the stack trace back, not print it out." – Manuel Romeiro Aug 10 '21 at 10:24
17

Silly me, it's Thread.currentThread().getStackTrace();

jjnguy
  • 136,852
  • 53
  • 295
  • 323
ripper234
  • 222,824
  • 274
  • 634
  • 905
17

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 );
}
Christian Ullenboom
  • 1,388
  • 3
  • 24
  • 20
16

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);
Evan Knowles
  • 7,426
  • 2
  • 37
  • 71
Witold Kaczurba
  • 9,845
  • 3
  • 58
  • 67
11

To string with guava:

Throwables.getStackTraceAsString(new Throwable())
Zitrax
  • 19,036
  • 20
  • 88
  • 110
10

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));
}
Salvador Valencia
  • 1,330
  • 1
  • 17
  • 26
  • This looks like one auto generated by Netbeans. – Leif Gruenwoldt Sep 12 '12 at 21:11
  • is logger a built in logger or one that you created and write to a file. – Doug Hauf Feb 15 '14 at 23:04
  • @Doug Hauf, logger is a reference to the built in Java Logger. Make sure you configure the logging.properties file. Add it at the beginning of your class like this: private static final Logger logger = Logger.getLogger( Your_Class_Name.class.getName() ); – Salvador Valencia Feb 17 '14 at 19:22
  • 1
    `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. – searchengine27 Nov 09 '16 at 19:57
  • @searchengine27 My comment was from 2012, are we talking the same version of Java? And take a chill pill. You came a little late with your reply my friend. – Salvador Valencia Nov 09 '16 at 20:24
  • 1
    It existed in 2012 too. Date doesn't make a difference in your case, unfortunately. See [link](docs.oracle.com/javase/1.5.0/docs/api/java/util/logging/Logger.html#log(java.util.logging.Level, java.lang.String, java.lang.Throwable)), [link](docs.oracle.com/javase/1.5.0/docs/api/java/util/logging/Logger.html#log(java.util.logging.LogRecord)), etc (there are several functions that pass the `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) – searchengine27 Nov 09 '16 at 20:36
8
try {
}
catch(Exception e) {
    StackTraceElement[] traceElements = e.getStackTrace();
    //...
}

or

Thread.currentThread().getStackTrace()
butterchicken
  • 13,583
  • 2
  • 33
  • 43
5

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Dinesh Kumar
  • 2,838
  • 1
  • 16
  • 18
5
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...
}
Zar E Ahmer
  • 33,936
  • 20
  • 234
  • 300
5

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
Sampath
  • 1,144
  • 1
  • 21
  • 38
4

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);
    }
}
2

For people, who just want to get the current stacktrace to their logs, I would go with:

getLogger().debug("Message", new Throwable());

Cheers

Kubach
  • 101
  • 1
  • 4
  • Don't forget that creating new instance of Throwable is a slow operation and will slowdown you code, even you disable debug level on log's. The best approach is validate if debug level is enabled "if (getLogger().isDebugEnabled()) {/*log code*/}. Anyway, the question was "I want to get the stack trace back, not print it out"... – Manuel Romeiro Aug 10 '21 at 10:19
0

You can also use exception to print stack instead of taking pain of putting new line char:

Exception e = new Exception();
e.setStackTrace(Thread.currentThread().getStackTrace());
loggr.info(e);
vishal
  • 32
  • 2
  • 8
-1

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

SkyWalker
  • 28,384
  • 14
  • 74
  • 132
Manov
  • 69
  • 6