用jstack定位死锁关键是运行jstack -l 并检查末尾“Found 1 deadlock.”提示,再比对BLOCKED线程的waiting to lock 与另一线程的locked 地址是否一致,形成循环等待闭环。

用 jstack 查看线程状态定位死锁,关键是关注 BLOCKED 和 WAITING 状态线程的锁持有与等待关系,并结合“Found 1 deadlock”提示快速确认。
运行 jstack 获取线程快照
在 Java 进程运行时,执行以下命令(需有对应进程权限):
-
jstack <pid></pid>:输出全部线程堆栈(最常用) -
jstack -l <pid></pid>:加-l参数可显示详细锁信息(包括可重入锁、条件队列、等待的 Monitor 等),对分析死锁至关重要 - 建议重定向保存:
jstack -l <pid> > thread_dump.txt</pid>,方便反复查看和比对
识别死锁的典型线索
死锁在线程 dump 中通常表现为循环等待:A 等 B 持有的锁,B 又等 A 持有的锁。重点关注以下内容:
- 线程状态为 java.lang.Thread.State: BLOCKED (on object monitor),且后面明确写出
waiting to lock - 另一处有线程状态为 java.lang.Thread.State: RUNNABLE 或 BLOCKED,并显示
locked—— 这个地址必须和前一线程等待的地址一致 - 多个线程互相
waiting to lock和locked同一组对象地址,形成闭环
直接利用 jstack 自动检测功能
jstack 内置了死锁检测逻辑,只要存在死锁,末尾一定会打印:
立即学习“Java免费学习笔记(深入)”;
Found 1 deadlock.
===================
"Thread-1":
at DeadlockExample$Task2.run(DeadlockExample.java:35)
- waiting to lock (a java.lang.Object)
- locked (a java.lang.Object)
"Thread-0":
at DeadlockExample$Task1.run(DeadlockExample.java:21)
- waiting to lock (a java.lang.Object)
- locked (a java.lang.Object)
这个区块是诊断死锁最高效的部分,无需人工遍历全部线程。
辅助验证与避坑提醒
仅靠单次 jstack 可能漏掉瞬时死锁或竞争窗口小的问题:
- 若未看到 “Found N deadlock”,不代表一定没有 —— 可能死锁刚解除,建议连续执行多次(如间隔 1 秒,连采 3–5 次)
- 注意区分 死锁(deadlock) 和 长时间阻塞(如 I/O、sleep、自旋):后者线程状态可能是
WAITING (parking)或TIMED_WAITING,不涉及 monitor 锁竞争 - 确保目标进程使用的是 JDK 自带的 HotSpot JVM;某些裁剪版或非 HotSpot VM(如 GraalVM native image)可能不支持完整 jstack 功能


















