There are, in fact, a very large number of ways of getting stack traces out of a JVM.
- If you send a system-dependent signal to your JVM process, it will spit out a stack dump of every currently live thread. On Solaris and Linux, the signal is a SIGQUIT, which you can get by using kill -3 on the JVM PID (or the PID of the parent JVM process under Linux 2.4), or hitting Control-\. On Windows, you can achieve the same effect by hitting Ctrl-Break on Windows.
- If you call Thread.dumpStack(), or create a new Throwable, and invoke getStackTrace() on it, you can get the current stack trace programmatically.
- If you use ThreadMXBean's getThreadInfo methods, you can get stack traces out of any threads you want.
- If you use JVMTI's GetStackTrace or GetAllStackTraces methods, you can get stack trace information in native code.
Most of these methods will tell you if your thread can be scheduled by the JVM or Operating System. This information will be reported as part of the thread info -- the thread will be described as "Runnable".
However, there is a big difference between "Runnable" and "Running". If you send a SIGPROF to your JVM and use AsyncGetCallTrace, you find out exactly what your JVM is doing at precisely the moment you sent the signal.
The difference here is fundamentally that all of those other methods tell you what the JVM could be doing, and this one tells you what it is doing. It will even tell you if it is performing garbage collection. This sort of information can be invaluable when you want to know what is soaking up your CPU cycles.