捕获Java线程转储(Thread Dump)的几种方法

线程转储是Java进程中所有线程状态的快照。每个线程的状态通过堆栈跟踪(Stack Trace)呈现,展示线程的调用栈内容。线程转储对诊断问题非常有用,因为它能揭示线程的活动信息。

线程转储以纯文本形式记录,因此可以保存到文件中,后续通过文本编辑器分析。以下章节将介绍多种工具和方法来生成线程转储。

JDK也提供了多种实用工具来捕获Java应用程序的线程转储。这些工具位于JDK安装目录的bin文件夹中。只要该目录在系统路径中,即可通过命令行调用它们。

1. jstack

jstack 是一个命令行工具,用于捕获线程转储。它接收进程的PID(进程ID)并将线程转储输出到控制台,也可以重定向到文件。

基本语法

代码语言:javascript代码运行次数:0运行复制
jstack [-l][-e] <pid>

选项:

■ -l:长格式列表。打印关于锁的附加信息。

■ -e:扩展格式列表。打印关于线程的附加信息。

■ -?-h--help-help:打印此帮助信息。

详细参考:.html

代码语言:javascript代码运行次数:0运行复制

(base) bogon:~ sdcui$ java -version
java version "21" 2023-09-19 LTS
Java(TM) SE Runtime Environment (build 21+35-LTS-2513)
Java HotSpot(TM) 64-Bit Server VM (build 21+35-LTS-2513, mixed mode, sharing)



(base) bogon:~ sdcui$ jstack 
Usage:
    jstack [-l][-e] <pid>
        (to connect to running process)
Options:
    -l  long listing. Prints additional information about locks
    -e  extended listing. Prints additional information about threads
    -? -h --help -help to print this help message

示例:

代码语言:javascript代码运行次数:0运行复制
jstack 17264 > /tmp/threaddump.txt  

1.2 jcmd

jcmd 是一个多功能命令行工具,通过向JVM发送指令实现多种操作。

基本语法

代码语言:javascript代码运行次数:0运行复制
jcmd <pid∣主类> <命令...∥PerfCounter.print∥−\[f文件]
或:jcmd -l
或:jcmd -h

命令必须是为选定的JVM提供的有效jcmd命令。 使用命令"help"查看可用命令。 如果pid为0,则命令将发送到所有Java进程。 主类参数将用于匹配(部分或完全)用于启动Java的类。 如果未提供任何选项,则列出Java进程(与-l相同)。

PerfCounter.print 显示该进程暴露的计数器 -f 从文件中读取并执行命令 -l 列出本地机器上的JVM进程 -?、-h、--help 打印此帮助信息

查看支持的命令:

代码语言:javascript代码运行次数:0运行复制


(base) bogon:~ sdcuike$ jcmd 67696 help command -all
67696:
Compiler.CodeHeap_Analytics
	Print CodeHeap analytics
Compiler.codecache
	Print code cache layout and bounds.
Compiler.codelist
	Print all compiled methods in code cache that are alive
Compiler.directives_add
	Add compiler directives from file.
Compiler.directives_clear
	Remove all compiler directives.
Compiler.directives_print
	Print all active compiler directives.
Compiler.directives_remove
	Remove latest added compiler directive.
Compiler.queue
	Print methods queued for compilation.
GC.class_histogram
	Provide statistics about the Java heap usage.
GC.finalizer_info
	Provide information about Java finalization queue.
GC.heap_dump
	Generate a HPROF format dump of the Java heap.
GC.heap_info
	Provide generic Java heap information.
GC.run
	Call java.lang.System.gc().
GC.run_finalization
	Call java.lang.System.runFinalization().
JFR.check
	Checks running JFR recording(s)
JFR.configure
	Configure JFR
JFR.dump
	Copies contents of a JFR recording to file. Either the name or the recording id must be specified.
JFR.start
	Starts a new JFR recording
JFR.stop
	Stops a JFR recording
JFR.view
	Display event data in predefined views
JVMTI.agent_load
	Load JVMTI native agent.
JVMTI.data_dump
	Signal the JVM to do a data-dump request for JVMTI.
ManagementAgent.start
	Start remote management agent.
ManagementAgent.start_local
	Start local management agent.
ManagementAgent.status
	Print the management agent status.
ManagementAgent.stop
	Stop remote management agent.
Thread.dump_to_file
	Dump threads, with stack traces, to a file in plain text or JSON format.
Thread.print
	Print all threads with stacktraces.
VM.cds
	Dump a static or dynamic shared archive including all shareable classes
VM.class_hierarchy
	Print a list of all loaded classes, indented to show the class hierarchy. The name of each class is followed by the ClassLoaderData* of its ClassLoader, or "null" if loaded by the bootstrap class loader.
VM.classes
	Print all loaded classes
VM.classloader_stats
	Print statistics about all ClassLoaders.
VM.classloaders
	Prints classloader hierarchy.
VMmand_line
	Print the command line used to start this VM instance.
VM.dynlibs
	Print loaded dynamic libraries.
VM.events
	Print VM event logs
VM.flags
	Print VM flag options and their current values.
VM.info
	Print information about JVM environment and status.
VM.log
	Lists current log configuration, enables/disables/configures a log output, or rotates all logs.
VM.metaspace
	Prints the statistics for the metaspace
VM.native_memory
	Print native memory usage
VM.set_flag
	Sets VM flag option using the provided value.
VM.stringtable
	Dump string table.
VM.symboltable
	Dump symbol table.
VM.system_properties
	Print system properties.
VM.systemdictionary
	Prints the statistics for dictionary hashtable sizes and bucket length
VM.uptime
	Print VM uptime.
VM.version
	Print JVM version information.
help
	For more information about a specific command use 'help <command>'. With no argument this will show a list of available commands. 'help all' will show help for all commands.

这里我们关注命令:

代码语言:javascript代码运行次数:0运行复制
Thread.print

详细参考.html

代码语言:javascript代码运行次数:0运行复制

(base) bogon:~ sdcui$ jcmd -h
Usage: jcmd <pid | main class> <command ...|PerfCounter.print|-f file>
   or: jcmd -l                                                    
   or: jcmd -h                                                    
                                                                  
  command must be a valid jcmd command for the selected jvm.      
  Use the command "help" to see which commands are available.   
  If the pid is 0, commands will be sent to all Java processes.   
  The main class argument will be used to match (either partially 
  or fully) the class used to start Java.                         
  If no options are given, lists Java processes (same as -l).     
                                                                  
  PerfCounter.print display the counters exposed by this process  
  -f  read and execute commands from the file                     
  -l  list JVM processes on the local machine                     
  -? -h --help print this help message  

示例:

代码语言:javascript代码运行次数:0运行复制
jcmd 17264 Thread.print  

1.3 kill -3命令(Linux/Unix)

在类Unix系统中,通过kill命令发送-3信号触发线程转储:

代码语言:javascript代码运行次数:0运行复制
kill -3 17264  

输出重定向: 通过以下JVM参数可将线程转储写入指定文件:

代码语言:javascript代码运行次数:0运行复制
-XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -XX:LogFile=~/jvm.log  

1.5 编程方式:使用ThreadMxBean

通过JMX(Java Management Extensions)的ThreadMxBean可编程生成线程转储。

示例代码

代码语言:javascript代码运行次数:0运行复制
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获取ThreadMXBean实例。

■ 调用dumpAllThreads()方法捕获线程转储,参数lockedMonitorslockedSynchronizers控制是否包含锁信息。

1.5 图形化工具

Java Mission Control (JMC)、jvisualvm、jconsole图形化工具也可以在合适的场景下使用。

结论

本文介绍了多种捕获Java线程转储的方法:

■ JDK工具

jstack、JMC、jvisualvm、jcmd、jconsole,各有适用场景。

■ 操作系统命令

kill -3(Unix/Linux)

■ 编程方式

通过JMX的ThreadMxBean动态生成。

推荐选择

  • Java 8+环境优先使用jcmd(功能全面)。
  • 图形化分析推荐JMC或jvisualvm。
  • 生产环境若无JDK工具,可通过操作系统信号或编程方式实现。

通过合理选择工具,可高效诊断多线程问题,优化应用性能。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。原始发表:2025-04-01,如有侵权请联系 cloudcommunity@tencent 删除dumpthread工具线程java