1. 概述
本文将介绍几种获取 Java 应用程序线程 Dump 的常用方法。
✅ 线程 Dump 是 Java 进程中所有线程状态的快照。每个线程的状态都以调用栈(stack trace)的形式呈现,展示该线程当前的执行路径。在排查性能瓶颈、死锁、线程阻塞等问题时,线程 Dump 是非常关键的诊断工具。
线程 Dump 以纯文本格式输出,因此我们可以将其保存为文件,后续使用文本编辑器或专业分析工具进行分析。
接下来,我们将介绍多种获取线程 Dump 的工具和方式,涵盖命令行、图形化工具以及编程方式。
2. 使用 JDK 工具
JDK 自带多个工具可用于生成线程 Dump。这些工具通常位于 JDK 安装目录的 bin
目录下。只要该目录已加入系统 PATH,就可以在命令行直接调用。
2.1. jstack
jstack
是一个命令行工具,用于输出指定 Java 进程的线程 Dump。它接收进程 ID(pid)作为参数,将结果打印到控制台,也可重定向到文件。
基本语法如下:
jstack [-F] [-l] [-m] <pid>
参数说明:
-F
:强制输出 Dump,适用于进程无响应(hang)时使用-l
:显示锁信息,包括可重入锁(ownable synchronizers)和 monitor 锁-m
:同时输出 native 帧(C/C++ 层调用栈),不仅限于 Java 栈
示例:将线程 Dump 保存到文件
jstack 17264 > /tmp/threaddump.txt
📌 小技巧:可通过 jps
命令快速获取 Java 进程的 pid。
2.2. Java Mission Control (JMC)
Java Mission Control 是一个功能强大的图形化监控与诊断工具,可连接本地或远程 JVM,实时采集性能数据。
启动 JMC 后,会列出本机运行的 Java 进程。右键选择目标进程,点击 “Start Flight Recording”,即可开始记录。在录制期间或结束后,可在 Threads 标签页查看线程 Dump 信息。
JMC 的优势在于低开销和丰富的上下文信息,适合生产环境长时间监控。
2.3. jvisualvm
jvisualvm
是一个集监控、线程分析、内存分析于一体的图形化工具,界面简洁直观。
右键点击 Java 进程,选择 “Thread Dump” 菜单,即可生成并查看线程 Dump,每个线程的调用栈都会清晰展示在新标签页中。
⚠️ 注意:从 JDK 9 开始,Oracle JDK 和 OpenJDK 默认不再包含 VisualVM。如需使用,可从 VisualVM 官方开源项目 单独下载。
2.4. jcmd
jcmd
是一个通用的 JVM 命令行工具,通过向 JVM 发送指令实现多种诊断功能。它不支持远程操作,必须在目标进程所在机器上运行。
获取线程 Dump 的命令如下:
jcmd 17264 Thread.print
✅ 推荐:从 Java 8 开始,jcmd
是首选工具,功能强大且统一。它整合了 jstack
、jmap
、jinfo
等多个工具的能力,是生产环境的“瑞士军刀”。
2.5. jconsole
jconsole
是 JDK 自带的 JMX 监控工具。连接目标 JVM 后,进入 Threads 标签页,即可查看每个线程的调用栈。
虽然功能不如 JMC 或 jvisualvm 强大,但胜在轻量,适合快速查看线程状态。
2.6. 工具对比总结
工具 | 优点 | 缺点 |
---|---|---|
jstack |
简单直接,适合快速抓取 | Java 8+ 推荐使用 jcmd 替代 |
JMC | 功能全面,低开销,适合生产环境 | 需额外学习成本 |
jvisualvm | 图形化,功能丰富,开源 | JDK 9+ 需单独安装 |
jcmd |
功能统一,推荐用于 Java 8+ | 无图形界面 |
jconsole |
轻量,JMX 原生支持 | 功能较基础 |
📌 建议:开发调试用 jvisualvm,生产环境优先使用 jcmd
或 JMC。
3. 命令行方式(无 JDK 环境)
在一些生产服务器上,出于安全考虑仅部署 JRE,此时无法使用 JDK 工具。但仍有以下替代方案。
3.1. kill -3
(Linux/Unix)
在类 Unix 系统中,可通过发送信号触发 JVM 输出线程 Dump:
kill -3 17264
✅ 该命令会向进程发送 SIGQUIT
信号,JVM 接收到后会将线程 Dump 打印到标准输出(通常是应用日志文件)。
若想将 Dump 写入指定文件,可启动 JVM 时添加以下参数:
-XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -XX:LogFile=~/jvm.log
此后执行 kill -3
,Dump 会同时输出到 ~/jvm.log
,方便集中收集。
3.2. Ctrl + Break(Windows)
在 Windows 系统中,可通过快捷键触发线程 Dump:
- 操作:在运行 Java 程序的控制台窗口,同时按下
Ctrl + Break
- 替代方案:某些键盘无
Break
键,可用Ctrl + Shift + Pause
替代
⚠️ 注意:输出会直接打印在控制台,若程序以服务方式运行(无控制台),则此方法无效。
4. 编程方式:使用 ThreadMXBean
除了外部工具,我们也可以在代码中主动获取线程 Dump,适用于自定义监控、健康检查等场景。
核心类:ThreadMXBean
,通过 JMX 提供线程管理接口。
示例代码:
private static String threadDump(boolean lockedMonitors, boolean lockedSynchronizers) {
StringBuffer threadDump = new StringBuffer(System.lineSeparator());
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
for(ThreadInfo threadInfo : threadMXBean.dumpAllThreads(lockedMonitors, lockedSynchronizers)) {
threadDump.append(threadInfo.toString());
}
return threadDump.toString();
}
关键步骤说明:
- 初始化
StringBuffer
用于拼接输出 - 通过
ManagementFactory.getThreadMXBean()
获取线程管理接口 - 调用
dumpAllThreads(lockedMonitors, lockedSynchronizers)
获取所有线程信息lockedMonitors = true
:包含线程持有的 monitor 锁lockedSynchronizers = true
:包含可重入锁(如 ReentrantLock)
- 遍历
ThreadInfo
数组,拼接为字符串返回
✅ 应用场景:可集成到 /actuator/threaddump
这类监控接口中,供运维人员一键获取。
5. 总结
本文系统介绍了获取 Java 线程 Dump 的多种方式:
- ✅ JDK 工具:
jstack
、jcmd
、JMC、jvisualvm、jconsole,适合开发和运维 - ✅ 命令行信号:
kill -3
和Ctrl+Break
,适用于无 JDK 环境 - ✅ 编程方式:通过
ThreadMXBean
实现,便于集成到应用内部
📌 实战建议:
- 日常调试:用 jvisualvm 或
jcmd
- 生产排查:优先
jcmd
+kill -3
配合日志收集 - 自动化监控:通过 JMX 接口暴露
/threaddump
接口
所有示例代码已托管至 GitHub:https://github.com/baeldung/core-java-modules/tree/master/core-java-perf