排查JVM线程死锁的核心是捕获并解读Thread Dump,它能精准定位相互阻塞的线程、锁及等待顺序;典型表现为静默卡死、接口超时、CPU不高但大量线程处于BLOCKED状态,可通过jstack -l、kill -3或Arthas thread -b等工具快速获取转储,并依据“Found one Java-level deadlock”提示及锁持有/等待关系还原循环链。

排查 JVM 中的线程死锁,核心是捕获并解读线程转储(Thread Dump),它能直接暴露线程间的锁等待循环。工具本身不修复死锁,但能准确定位哪几个线程、哪几把锁、以什么顺序相互阻塞。
观察典型死锁现象
死锁不是 CPU 飙高或内存暴涨,而是“静默卡死”:接口持续超时、后台任务停滞、服务看似运行但无响应;此时用 jps 能查到进程还在,top 看 CPU 使用率却不高——因为阻塞线程不消耗 CPU,只是空等。
- 多数线程状态为 BLOCKED,而非 RUNNABLE 或 WAITING
- 线程池活跃线程数长期为 0,但队列积压任务越来越多
- 日志中不再有新业务打印,也无明显异常堆栈
快速获取线程转储
无需重启应用,几种常用方式按场景选择:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
命令行一键抓取:执行
jstack <PID> > dump.log(PID 用jps -l查);生产环境推荐加-l参数显示锁详细信息 -
系统信号触发:对 Java 进程发
kill -3 <PID>,JVM 自动将转储输出到应用标准错误流(通常是 catalina.out 或 nohup.out) -
Arthas 实时诊断:连上后执行
thread -b,可直接列出所有已检测到的死锁线程及锁路径,适合不能停机的线上环境 - JVisualVM / JConsole 图形化:连接后点“线程”页签 → “线程转储”,工具会自动高亮“Found one Java-level deadlock”段落
从转储中识别死锁线索
重点不是看全部内容,而是锁定三类关键信息:
- 死锁声明头:搜索 “Found one Java-level deadlock”,这是 JVM 自带检测器的明确结论
-
线程状态与锁关系:每个涉及线程会标注类似
locked <0x000000076b45a290>(持有)和waiting to lock <0x000000076b45a2c0>(等待) - 循环链还原:比如 Thread-A 持有锁 L1 等待 L2,Thread-B 持有 L2 等待 L1 —— 两行信息就能串起闭环,这就是死锁根源
定位代码中的问题模式
转储只告诉你“谁在等谁”,真正修复要回溯到源码。常见可复现的模式包括:
- 嵌套 synchronized 错序:一个方法先锁 accountA 再锁 accountB,另一个并发调用却先锁 accountB 再锁 accountA
- 动态对象锁未排序:转账操作中,两个账户对象 hash 值不同,导致不同线程加锁顺序不一致
- 混用显式锁与内置锁:部分逻辑用 ReentrantLock,部分用 synchronized,锁粒度和范围不统一,容易遗漏协调
- 锁内调用外部方法:synchronized 块里调用了可能间接获取其他锁的第三方方法,引入隐式依赖

















