jstat 和 jstack 是 jdk 自带的轻量级命令行工具,分别用于实时监控 jvm 内存/gc 状态和抓取线程快照;jstat -gcutil 查内存使用率,jstat -gc 观察 gc 频次与耗时,jstack -l 定位死锁与高 cpu 线程,二者配合可高效排查响应慢、卡顿、死锁等问题。

jstat 和 jstack 是 JDK 自带的轻量级命令行工具,不需要额外安装,开箱即用。它们分别聚焦于 JVM 运行时统计信息和线程状态诊断,是线上问题排查最常优先使用的两个工具。
jstat:看 JVM 内存与 GC 实时表现
它像一个实时仪表盘,不侵入应用、不暂停服务,适合持续观察。核心用法围绕 进程 ID(PID) 和 监控维度选项 展开:
-
先查 PID:用
jps -l列出所有 Java 进程及其主类,快速定位目标应用 -
看内存使用率(最常用):执行
jstat -gcutil <pid></pid>,输出各内存区(Eden、老年代、元空间等)使用百分比,例如E(Eden)长期 >90% 就提示可能频繁新生代 GC -
看 GC 频次与耗时:用
jstat -gc <pid> 2000 5</pid>,每 2 秒打印一次 GC 统计,共 5 次;重点关注YGC(年轻代次数)、YGCT(年轻代总耗时)、FGC(Full GC 次数)——如果 FGC 增长快或 FGCT 单次超 1 秒,说明老年代压力大或存在内存泄漏 -
看类加载行为:运行
jstat -class <pid></pid>,若Loaded持续上涨且Unloaded很少,可能是动态生成类(如某些 ORM 或脚本引擎)引发的问题
jstack:抓线程快照,定位卡顿与死锁
它能瞬间捕获 JVM 所有线程的调用栈,是分析“CPU 高但业务无响应”、“接口超时”、“疑似死锁”的第一手证据:
-
基础抓取:直接执行
jstack <pid></pid>,输出会显示每个线程名、状态(如RUNNABLE、WAITING、BLOCKED)、锁持有/等待关系,以及完整方法调用链 -
加锁详情(关键!):用
jstack -l <pid></pid>,可看到java.util.concurrent锁(如 ReentrantLock)的持有者和等待队列,对排查死锁非常直观 -
导出到文件便于分析:执行
jstack <pid> > thread_dump.log</pid>,后续可用文本工具搜索关键词(如WAITING on、locked )快速定位阻塞点 -
配合 top 定位高 CPU 线程:在 Linux 上先用
top -Hp <pid></pid>找出占用 CPU 最高的线程 TID(十进制),转为十六进制后,在 jstack 输出中搜索该 nid,就能精确定位是哪段代码在疯狂执行
两个工具配合使用的典型场景
比如服务响应变慢,可按顺序操作:
- 用
jps确认进程 ID - 用
jstat -gcutil <pid> 1000</pid>观察 10 秒内 GC 是否异常(如老年代使用率飙升、Full GC 频发) - 同时用
jstack -l <pid> > dump.log</pid>抓多份快照(间隔 2–3 秒),对比看是否有线程长时间停留在同一方法(如数据库连接等待、远程 HTTP 调用未返回) - 若发现多个线程都
waiting to lock同一把锁,基本可确认死锁;若大量线程处于WAITING on java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject,可能是线程池满或下游依赖超时未处理
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











