cult. There is no guarantee that the parser in the online examples won't need to be tweaked
for your particular JVM.
The basic output of the jstack parser looks like this:
% jstack pid > jstack.out
% java ParseJStack jstack.out
Threads in start Running
8 threads in java.lang.Throwable.getStackTraceElement(Native
Total Running Threads: 8
Threads in state Blocked by Locks
41 threads running in
Total Blocked by Locks Threads: 41
Threads in state Waiting for notify
39 threads running in
18 threads running in System Thread
Total Waiting for notify Threads: 74
Threads in state Waiting for I/O read
14 threads running in com.acme.MyServlet.doGet(MyServlet.java:603)
Total Waiting for I/O read Threads: 14
The parser aggregates all the threads and shows how many are in various states. Eight
threads are currently running (they happen to be doing a stack trace—a quite expensive oper-
ation which is better to avoid).
Forty-one threads are blocked by a lock. The method reported is the first non-JDK method in
the stack trace, which in this example is the GlassFish method EJBClassLoad-
er.getResourceAsStream() . The next step would be to consult the stack trace and search
for that method and see what resource the thread is blocked on.
In this example, all the threads were blocked waiting to read the same JAR file, and the stack
trace for those threads showed that all the calls came from instantiating a new SAX parser.
As discussed in Chapter 10 , the SAX parser can be defined dynamically by listing the re-
source in the manifest file of the application's JAR files, which means that the JDK must