Detecting Deadlock in Java — jstack, ThreadMXBean, and Dump Analysis
Fast recall
Quick revision
Core answer
Thread.dump_to_file; (3) Send `SIGQUIT` (kill -3 on Unix) — JVM prints dump to its stdout. Programmatically, use `ThreadMXBean.findDeadlockedThreads()` — returns thread IDs of any deadlocked threads; this is how monitoring systems detect deadlocks automatically. For a textbook deadlock (thread A holds lock X, waiting for Y; thread B holds Y, waiting for X), the JVM auto-detects and reports the cycle. For livelocks or non-monitor-based deadlocks (e.g., on ReentrantLock), you must inspect the stack traces manually.Whether the candidate knows the mechanics of thread dumps, can read jstack/jcmd output, and knows about programmatic detection via ThreadMXBean
Only checking CPU usage (deadlocks are 0% CPU, not high). Not knowing jstack/jcmd syntax. Assuming all deadlocks are auto-reported — ReentrantLock deadlocks may require manual analysis
Mention `jcmd Thread.print -l` for lock info; `ThreadMXBean.findDeadlockedThreads` for automated alerting; that Java 21's thread dump format differs for virtual threads; and taking multiple dumps 5-10s apart to confirm the state is stable
Interview-ready guide
Interview answer
Deadlock detection has two flavors: manual thread dump analysis and programmatic via ThreadMXBean.
Symptoms
- Hung requests, frozen app
- CPU near 0% (threads parked, not spinning)
- Heap doesn't grow
- Specific endpoints stop responding
Capturing a thread dump
jstack— simplest, prints to stdoutjstack -l— includes lock infojcmd— modern replacementThread.print -l kill -3(SIGQUIT) — JVM prints dump to its stdout- Take two dumps 5-10s apart to confirm threads are actually stuck
Reading the dump
- Look at bottom of output: "Found one Java-level deadlock" section
- JVM auto-detects monitor (
synchronized) deadlocks and spells out the cycle - Each thread shows: held monitor + waiting monitor + stack trace
- Line numbers tell you exactly where the bug is
Thread states that matter
- `BLOCKED` = waiting for monitor; see
- waiting to lock - `WAITING (parking)` = parked via
LockSupport.park, typicallyReentrantLock; see- parking to wait for - `WAITING (on object monitor)` =
Object.wait()— waiting fornotify - `RUNNABLE` threads stuck here = tight loop, not deadlock
The ReentrantLock gap
- JVM auto-detector only covers `synchronized`
ReentrantLock,ReadWriteLock,Semaphoredeadlocks do NOT appear in the "Found deadlock" section- Must manually trace: threads parked → which lock instance → who holds it → is there a cycle?
Programmatic detection — the production answer
ManagementFactory.getThreadMXBean().findDeadlockedThreads()- Covers all lock types (monitor and Lock)
- Returns thread IDs; use
getThreadInfo(ids, true, true)for full info - Schedule every 30–60 seconds; alert on-call when it fires
- This is how real monitoring works at scale
Java 21 virtual threads
- Millions of threads makes a text dump huge
- Use
jcmdfor structured outputThread.dump_to_file -format=json - Query with
jq jstackstill works but only sees mounted + platform threadsThreadMXBean.findDeadlockedThreads()still works
Best practices
- Always take two dumps 5-10s apart — confirms genuinely stuck
- In production, run
findDeadlockedThreadsperiodically as part of health checks - Alert immediately on detection — deadlocks rarely self-heal
- Annotate dumps with timestamp and which threads form the cycle before escalation
Watch out for
- Container permissions: ptrace/
jstackmay be blocked in Kubernetes; ensurejcmdpaths work - Heap dumps ≠ thread dumps — don't confuse the two
- `jstack -F` for force attach when JVM is unresponsive — last resort
Recommendation: Bake automated deadlock detection via ThreadMXBean.findDeadlockedThreads() into every production service — run it on a 30–60 second schedule as part of health checks, and alert on-call the moment it fires. For on-demand debugging, use `jcmd jstack -l (classic); always take two dumps 5-10 seconds apart to confirm threads are actually stuck versus making slow progress. Look for the "Found one Java-level deadlock" section for monitor deadlocks — the JVM hands you the cycle on a plate. For ReentrantLock deadlocks there's no auto-report, so know how to read the parked stack traces. On Java 21, use jcmd Thread.dump_to_file -format=json for dumps that include virtual threads. And don't confuse deadlock (0% CPU) with a tight loop (100% CPU) or slow downstream (some CPU, waiting on external) — each has a different fingerprint in a dump.
Detecting Deadlock in Java — jstack, ThreadMXBean, and Dump Analysis
Direct Answer
Take a thread dump of the running JVM and look for threads in BLOCKED state waiting on monitors, plus the JVM's explicit "Found one Java-level deadlock" section at the bottom of the output. Three ways to capture: (1) jstack <pid> — the simplest, prints directly to stdout; (2) jcmd <pid> Thread.print — modern replacement, also works for virtual threads with Thread.dump_to_file; (3) Send SIGQUIT (kill -3 <pid> on Unix) — JVM prints dump to its stdout. Programmatically, use ThreadMXBean.findDeadlockedThreads() — returns thread IDs of any deadlocked threads; this is how monitoring systems detect deadlocks automatically. For a textbook deadlock (thread A holds lock X, waiting for Y; thread B holds Y, waiting for X), the JVM auto-detects and reports the cycle. For livelocks or non-monitor-based deadlocks (e.g., on ReentrantLock), you must inspect the stack traces manually.
Common Mistakes & Pitfalls
Only checking CPU usage (deadlocks are 0% CPU, not high). Not knowing jstack/jcmd syntax. Assuming all deadlocks are auto-reported — ReentrantLock deadlocks may require manual analysis
Check your understanding
Answer these without looking back at the article.
- Why does `ThreadMXBean.findDeadlockedThreads` find `ReentrantLock` deadlocks but the built-in dump detector doesn't?
- How would you distinguish a deadlock from a slow database query in a thread dump?
- What's the difference between `BLOCKED` and `WAITING (parking)` states?
- How do thread dumps work with millions of virtual threads on Java 21?
- Can you detect livelocks with `findDeadlockedThreads`? Why or why not?
Related interview prep categories
2Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.