How to read a JVM thread dump

Paste the output of jstack or jcmd Thread.print, or open a .txt or .log file, and press Analyze locally. The dump is read in this browser: the summary counts the threads by java.lang.Thread.State, the card below ranks the stack frames that repeat, and the findings name the threads waiting on a lock that another thread holds.

A 13-thread sample of 4.3 KB came back as RUNNABLE 4, WAITING 3, BLOCKED 2, TIMED_WAITING 2 and UNKNOWN 2, with java.base/java.lang.Thread.sleep(Native Method) as the most repeated frame (3 threads) and two HTTP workers waiting on the monitor that cache-writer held. Nothing is uploaded and no copy of the dump is kept.

  1. Paste the dump into the box, or drop a .txt or .log file on it. jstack, jstack -l and jcmd <pid> Thread.print output all work; the file name stays next to the box and disappears as soon as you paste something else.
  2. Press Analyze locally. The summary card shows one row per state name, the card below lists the twelve most frequent frames with their counts, and both fill in during the same pass.
  3. Read the findings list: a Java-level deadlock is reported once and then split into the threads that wait for each other, and a lock that one thread waits for while another holds it is named with both sides.
  4. Take the result with Copy, or press Download for a plain-text report named after the file you loaded (thread-dump-analysis.txt when you pasted). The report carries the counts, the state table, the top frames and the findings, not the dump you pasted.
  5. Clear empties the box, the tables and the findings and restores the placeholder text; the page keeps nothing afterwards.

What the tables and findings mean

Input the analyzer reads

Only text is parsed, and only the shapes a JVM dump writes: thread headers (a quoted name followed by prio=, tid= or nid=), java.lang.Thread.State lines, at frames, and the waiting to lock / locked / parking to wait for lines that jstack -l adds. VM threads are printed without a state line, so they land in the UNKNOWN row — two of the thirteen in the sample above.

The deadlock report that jstack appends after the thread list is read as a report, not as more threads: a dump with three threads and one deadlock stays three threads, and the report becomes one finding plus one line per waiting pair.

How the numbers are counted

Every frame of every thread counts, not only the three innermost ones, because a shared frame that sits deeper in the stack is what a repeating call path looks like. In a 24-thread sample whose fifth frame is java.base/java.lang.reflect.Method.invoke(Method.java:568), that frame appears 18 times in the dump and in the table.

A lock correlation needs both halves in the same snapshot: the waiting to lock <id> line of one thread and the locked <id> line of another. Locks whose owner is not in the file — a truncated dump, or jstack run without -l — are still counted as waits, but nothing is claimed about who holds them.

Size is not a practical limit: a 240-thread dump of 92 KB came back with 240 threads, 6 of them blocked on a single monitor and three frames counted 240 times each, because the work happens on this machine.

Limits & compatibility

A HotSpot crash log (hs_err_pid*.log) lists Java threads but carries no java.lang.Thread.State line, so the page says exactly that instead of drawing empty tables. Any other text without a single thread header is answered the same way, and an empty box gets a warning rather than a result.

One dump is read at a time. The analyzer does not attach to a JVM, cannot sample a running process and does not watch a file for changes; for a live view, Flight Recorder or a profiler is the right instrument.

State names, frame signatures and lock ids are printed exactly as the dump writes them, in English, because they are data; the labels around them follow the page language.

Recent tools: