jstack 是 jvm 自带的轻量级诊断工具,用于抓取线程快照以分析线程状态、锁竞争和死锁;通过 jps 获取 pid,执行 jstack -l 生成含锁信息的 dump,结合 top 定位高 cpu 线程。

jstack 是 JVM 自带的轻量级诊断工具,专用于抓取线程快照(Thread Dump),直接反映运行中 Java 进程的实时线程状态、锁持有关系和调用栈。它不依赖代码修改,也不需重启服务,是排查死锁、高 CPU、线程阻塞等问题的第一手依据。
获取进程 PID 并生成基础线程快照
先确认目标 Java 进程 ID:
- 执行
jps -l列出所有 Java 进程及其主类全限定名 - 若进程较多,可结合
ps aux | grep java或jps -m(显示启动参数)辅助识别 - 拿到 PID 后,执行
jstack <pid></pid>输出到终端;建议重定向保存:jstack <pid> > dump.log</pid>
此时输出包含每个线程的名称、优先级、nid(本地线程 ID)、状态(如 RUNNABLE、BLOCKED)及完整方法调用链。
识别关键线程状态与锁线索
重点关注以下几类信息:
-
BLOCKED:线程在等待进入 synchronized 块或方法,已显示
waiting to lock—— 表明它正争抢某把对象锁 -
WAITING / TIMED_WAITING:可能因
Object.wait()、Thread.join()或LockSupport.park()挂起,需结合栈顶方法判断是否合理 -
locked:表示该线程当前持有某对象监视器,是分析锁归属的关键标记 - 同一锁地址(如
0x000000076c12a3b0)同时出现在多个线程的waiting to lock和locked中,即存在锁竞争或死锁苗头
精准定位死锁:用 -l 参数并检查结尾提示
死锁不是靠人工逐行比对发现的,jstack 会自动检测并汇总:
- 务必使用
jstack -l <pid></pid>,-l 开启锁详细模式,确保显示锁对象地址和持有者 - 生成后直接搜索关键词
Found one Java-level deadlock - 若存在死锁,结尾会明确列出互相等待的线程对,例如:
"Thread-1": waiting to lock monitor 0x00007f8b4800a800 (object 0x00000000f1a1b1d8), which is held by "Thread-2"
"Thread-2": waiting to lock monitor 0x00007f8b4800b800 (object 0x00000000f1a1b1e0), which is held by "Thread-1" - 顺着提示中的线程名,回溯各自堆栈,就能定位到具体哪两段代码分别持有了对方需要的锁
配合操作系统快速关联高负载线程
当发现某个线程持续 RUNNABLE 且 CPU 占用异常高时:
- 用
top -H -p <pid></pid>查看进程中各 native 线程的 CPU 使用率 - 记下高 CPU 的线程 tid(十进制),转为十六进制(如 12345 → 0x3039)
- 在 jstack 输出中查找
nid=0x3039对应的线程,即可锁定其 Java 栈帧,判断是否陷入死循环、密集计算或无界迭代
这种 JVM 层与 OS 层的交叉验证,能避免仅看 Java 栈而忽略 native 调用导致的误判。











