java死锁必须通过jstack -l获取线程堆栈定位,重点分析blocked状态、waiting to lock与locked地址闭环;threadmxbean可检测synchronized死锁但不支持reentrantlock,生产环境需定时采样并结合可视化工具分析。

Java 线程发生死锁时,不能靠日志或代码“猜”,必须获取线程的实时堆栈信息,才能准确定位哪几个线程互相持有/等待哪些锁。核心方法是利用 JVM 自带的线程快照工具,结合堆栈中 java.lang.Thread.State: BLOCKED 和 waiting to lock / locked ownable synchronizers 等关键线索来分析。
用 jstack 抓取线程快照定位死锁
jstack 是 JDK 自带命令,能直接输出 JVM 所有线程的堆栈和锁状态。对疑似死锁的 Java 进程执行:
-
jstack -l
> thread_dump.txt (-l参数必须加,否则不显示锁详情) - 打开
thread_dump.txt,搜索 "Found one Java-level deadlock" —— 如果 JVM 检测到经典死锁,会自动标出涉及的线程、锁对象和调用栈 - 若没自动提示,需手动查找:找状态为
BLOCKED的线程,看它waiting to lock 0x...的地址;再搜这个地址是否被另一个线程locked或owned by
在代码中主动检测并打印死锁信息
可在运行时调用 ThreadMXBean 接口,程序化检查死锁:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 获取管理接口:
ThreadMXBean bean = ManagementFactory.getThreadMXBean(); - 调用
long[] deadlockedIds = bean.findDeadlockedThreads();(仅检测synchronized锁,不包含java.util.concurrent中的显式锁) - 若有返回 ID 数组,用
bean.getThreadInfo(deadlockedIds, Integer.MAX_VALUE)获取完整堆栈,直接打印或记录 - 注意:该方法不会检测
ReentrantLock.lock()类型的死锁,如需全面覆盖,建议配合jstack -l使用
分析堆栈时重点关注的关键词和结构
一份有效的线程堆栈里,死锁线索往往藏在几行之内:
- "java.lang.Thread.State: BLOCKED (on object monitor)":说明线程卡在进入 synchronized 块
- "waiting to lock ":它想获取的对象监视器地址
- "locked " 或 "locked ownable synchronizer"(如 ReentrantLock):另一线程已持该锁
- 连续比对两个(或多个)线程的 “waiting to lock” 和 “locked” 地址,形成闭环即确认死锁
生产环境建议:定期采样 + 可视化辅助
单次 jstack 可能错过瞬时死锁,建议:
- 写脚本定时执行
jstack -l <pid></pid>并保存带时间戳的文件(如每 30 秒一次,保留最近 10 份) - 用 jstack-analyzer 或 fastthread.io 在线上传分析,自动生成死锁图和线程依赖关系
- 在关键同步块前后打日志,记录线程名、锁对象 identityHashCode、进入/退出时间(注意避免日志本身影响锁行为)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










