java死锁排查核心是快速确认“谁在等谁”,需结合jstack(抓取并识别死锁现场)、jconsole(图形化检测)和visualvm(辅助分析复杂线程状态),再通过锁对象hashcode反查代码中锁获取顺序。

用 jstack 抓取并识别死锁现场
jstack 是最直接、零依赖的命令行工具,适合所有环境,尤其线上紧急排查。
- 先用 jps -l 找到目标 Java 进程 ID(例如输出 12345 com.example.Main)
- 执行 jstack -l 12345 > threaddump.txt,-l 参数必须加,它会显示锁 owner 和 waiting threads 的完整信息
- 打开文件,直接搜索关键词 Found one Java-level deadlock —— 如果存在死锁,jstack 会在末尾明确列出所有卷入线程、各自持有的锁(如 java.lang.Object@7a81197d)、以及正在等待的锁对象
- 重点关注每条线程堆栈中 waiting to lock 和 locked 对应的 object identity hashcode,它们是定位代码中 synchronized 块或 Lock 实例的关键线索
用 JConsole 图形化检测死锁
JConsole 适合开发或测试环境快速验证,操作直观,还能实时查看线程状态变化。
- 启动 jconsole,选择对应进程连接(若远程需开启 JMX)
- 切换到 “线程” 标签页,点击右上角 “检测死锁” 按钮
- 界面会立即标出死锁线程,并高亮显示:每个线程当前堆栈、持有锁(含类名 + identity hashcode)、等待锁、阻塞来源
- 双击任一死锁线程,可展开完整调用链,快速跳转到源码中 synchronized 或 lock.lock() 行
用 VisualVM 辅助分析复杂线程状态
当 jstack 输出难以解读,或需结合 CPU、内存、线程生命周期综合判断时,VisualVM 更有优势。
- 启动 VisualVM,连接目标进程,安装 Threads 插件(如未默认启用)
- 进入 “Threads” 页签,点击 “Thread Dump” 按钮生成快照
- 它会自动标记 deadlock 状态线程,并以颜色区分 WAITING / BLOCKED 线程;点击线程可查看锁对象详情和堆栈
- 支持对比多个 dump 文件,观察死锁是否持续存在,或随请求量增长而复现
关键细节不能漏
工具只是放大镜,真正定位根因要靠人工对照:
- 把 jstack 中出现的锁对象 hashcode(如 java.lang.Object@7a81197d)复制出来,在代码里全局搜索 —— 它大概率对应某个 synchronized(obj) 或 ReentrantLock 实例变量
- 检查这些锁是否被多个线程以**不同顺序**获取(比如 A→B vs B→A),这是循环等待的典型诱因
- 留意 synchronized 块内部是否调用了可能阻塞的操作(如 IO、远程调用、另一个锁),这会拉长持锁时间,放大死锁概率
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











