54

For diagnostic purposes I sometimes need to store the call stack that lead to a given state transition (such as granting a lock, committing a transaction, etc.) so that when something goes wrong later I can find out who originally triggered the state transition.

Currently, the only way I am aware of to retrieve the call stack looks like the following code snippet, which I consider terribly ugly:

StackTraceElement[] cause;
try {
  throw new Exception();
} catch (Exception e) {
  cause = e.getStackTrace();
}

Does somebody know of a better way to accomplish this?

Gray
  • 112,334
  • 22
  • 281
  • 349
Thilo-Alexander Ginkel
  • 6,808
  • 10
  • 43
  • 56

4 Answers4

104

I think you can get the same thing with:

StackTraceElement[] cause = Thread.currentThread().getStackTrace();
bruno conde
  • 47,131
  • 14
  • 97
  • 117
  • As @nyx noted in their answer below, Java 9 introduced StackWalker, which might have better performance any some cases (see https://stackoverflow.com/a/49091729). – MyKey_ Jan 10 '22 at 18:18
17

Well, you can improve it slightly by not actually throwing the exception.

Exception ex = new Exception();
ex.fillInStackTrace();
StackTraceElement[] cause = ex.getStackTrace();

Actually, I just checked: the constructor calls fillInStackTrace() already. So you can simplify it to:

StackTraceElement[] cause = new Exception().getStackTrace();

This is actually what Thread.getStackTrace() does if it's called on the current thread, so you might prefer using it instead.

Michael Myers
  • 184,092
  • 45
  • 284
  • 291
  • No need for `fillInStackTrace` (although it is easy to read its API docs backwards). – Tom Hawtin - tackline Apr 01 '09 at 16:16
  • The .class file/source I'm looking at right now calls native `Thread.dumpThreads()` rather than using a dummy exception. OpenJDK- 11+28_windows-x64_bin. Hyphen, plus, underscore, hyphen, underscore? I'm not mad, I'm just disappointed. – Mark Storer Aug 14 '19 at 15:20
3

If you want it as a String and use Apache Commons:

org.apache.commons.lang.exception.ExceptionUtils.getFullStackTrace(new Throwable())
Edward Anderson
  • 12,971
  • 4
  • 51
  • 47
2

There's a new option since JDK 9: StackWalker

It isn't as expensive as Thread.currentThread().getStackTrace().

see also How Expensive is Thread.getStackTrace()?

nyx
  • 455
  • 1
  • 4
  • 10