获取Java线程转储的常用方法(推荐)
作者:铁锚 发布时间:2023-05-15 02:30:19
1. 线程转储简介
线程转储(Thread Dump)就是JVM中所有线程状态信息的一次快照。
线程转储一般使用文本格式, 可以将其保存到文本文件中, 然后人工查看和分析, 或者使用工具/API自动分析。
Java中的线程模型, 直接使用了操作系统的线程调度模型, 只进行简单的封装。
线程调用栈, 也称为方法调用栈。 比如在程序执行过程中, 有一连串的方法调用链:obj1.method2
调用了obj2.methodB
,obj2.methodB
又调用了obj3.methodC
。 每个线程的状态都可以通过这种调用栈来表示。
线程转储展示了各个线程的行为, 对于诊断和排查问题非常有用。
下面我们通过具体示例, 来演示各种获取Java线程转储的工具, 以及使用方法。
2. 使用JDK自带的工具
我们一般使用JDK自带的命令行工具来获取Java应用程序的线程转储。 这些工具都在JDK主目录的bin文件夹下。
所以, 只要配置好 PATH 路径即可。 如果不会配置, 可以参考:JDK环境准备
2.1 jstack 工具
jstack 是JDK内置的一款命令行工具, 专门用来查看线程状态, 也可以用来执行线程转储。
一般先通过jps
或者ps
命令找到Java进程对应的pid, 然后在控制台中通过pid来输出线程转储。 当然, 我们也可以将输出内容重定向到某个文件中。
使用jstack工具获取线程转储的基本参数格式为:
jstack [-F] [-l] [-m] <pid>
下面请看具体的演示:
# 1. 查看帮助信息
jstack -help
输出的内容类似于:
Usage:
jstack [-l] <pid>
(to connect to running process)
jstack -F [-m] [-l] <pid>
(to connect to a hung process)
jstack [-m] [-l] <executable> <core>
(to connect to a core file)
jstack [-m] [-l] [server_id@]<remote server IP or hostname>
(to connect to a remote debug server)
Options:
-F to force a thread dump. Use when jstack <pid> does not respond (process is hung)
-m to print both java and native frames (mixed mode)
-l long listing. Prints additional information about locks
-h or -help to print this help message
对应的参数选项是可选的。 具体含义如下:
-F
选项, 强制执行线程转储; 有时候jstack pid
会假死, 则可以加上-F
标志-l
选项, 会查找堆内存中拥有的同步器以及资源锁-m
选项, 额外打印 native栈帧(C和C++的)
例如, 获取线程转储并将结果输出到文件:
jstack -F 17264 > /tmp/threaddump.txt
使用jps
命令可以获取本地Java进程的 pid。
2.2 Java Mission Control
Java Mission Control(JMC)是一款客户端图形界面工具, 用于收集和分析Java应用程序的各种数据。
启动JMC后, 首先会显示本地计算机上运行的Java进程列表。 当然也可以通过JMC连接到远程Java进程。
可以鼠标右键单击对应的进程, 选择 “Start Flight Recording(开始飞行记录)” 。 结束之后, “Threads(线程)” 选项卡会显示“线程转储”:
2.3 jvisualvm
jvisualvm 是一款客户端图形界面工具, 既简单又实用, 可用来监控 Java应用程序, 对JVM进行故障排查和性能分析。
也可以用来获取线程转储。 鼠标右键单击Java进程, 选择“ Thread Dump”选项, 则可以创建线程转储, 完成后会在新选项卡中自动打开:
2.4 jcmd
jcmd工具本质上是向目标JVM发送一串命令。 尽管支持很多功能, 但不支持连接远程JVM - 只能在Java进程的本地机器上使用。
其中一个命令是Thread.print
, 用来获取线程转储, 示例用法如下:
jcmd 17264 Thread.print
2.5 jconsole
jconsole 工具也可以查看线程栈跟踪。
打开jconsole并连接到正在运行的Java进程, 导航到“线程”选项卡, 可以查看每个线程的堆栈跟踪:
2.6 小结
事实证明, 可以使用JDK中的很多工具来获取线程转储。 让我们回顾一下, 并总结它们的优缺点:
jstack
jmc
jvisualvm
jcmd
jconsole
3. 使用Linux命令
在企业应用服务器中, 出于安全原因, 可能只安装了 JRE。 这时候没法使用这些JDK内置的工具。
但还是有办法获取线程转储。
3.1 使用kill -3
指令
在Unix/Linux之类的系统中, 可以使用kill
命令获取线程转储, 底层实现原理, 则是通过系统调用kill()
将信号参数发送给进程。 这里需要发送的是-3
信号。
一般先通过jps
找到JAVA进程对应的pid,kill -3
使用示例如下:
kill -3 17264
3.2Ctrl + Break
(Windows)
在Windows操作系统的命令行窗口中, 可使用组合键Ctrl + Break
来获取线程转储。 当然, 需要先导航至启动Java程序的控制台窗口, 然后同时按下CTRL
键和Break
键。
需要注意的是, 某些键盘是没有 “Break
” 键的。
在这种情况下, 可以组合使用CTRL
,SHIFT
, 以及Pause
键。
这两个命令都可以将线程转储打印到控制台。
4. 通过编程方式使用ThreadMxBean
JMX技术支持各种各样的花式操作。 可通过ThreadMxBean
来执行线程转储。
示例代码如下:
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();
}
上面代码做的事情很简单, 先通过ManagementFactory
获取ThreadMxBean
对象。
方法的布尔参数lockedMonitors
和lockedSynchronizers
, 表示是否导出持有的同步器和管程锁。
5. 总结
我们通过具体示例展示了获取线程转储的各种方法。
首先介绍的是各种JDK内置工具,
然后讨论了命令行方式,
最后介绍了JMX编程的方式。
完整的示例代码请参考GitHub仓库。
来源:https://blog.csdn.net/renfufei/article/details/112339222


猜你喜欢
- 说明:当程序中出现频繁变化的数据时,如果采用认为的方式进行修改并且编译打包则会导致代码的耦合性较高,不便于维护!所以能否为属性动
- 我们已经尝试去定义类。定义类,就是新建了一种类型(type)。有了类,我们接着构造相应类型的对象。更进一步,每个类型还应该有一个清晰的接口(
- 可重入锁,从字面来理解,就是可以重复进入的锁。可重入锁,也叫做递归锁,指的是同一线程外层函数获得锁之后,内层递归函数仍然有获取该锁的代码,但
- 由于公司平台访问人数逐渐增多,公司项目的数据库已经几次出现宕机现象。为减轻数据库压力,我上个月对公司项目做了下调整。把新闻板块提取出来单独一
- 这篇文章主要介绍了Maven打包jar生成javadoc文件和source文件代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作
- 本文实例为大家分享了C# Email发送邮件的具体代码,供大家参考,具体内容如下//回执地址 var Receipt = &q
- 介绍INI文件格式由节、键、值组成。节[section]参数(键=值)name=value1.创建一个ini文件在Debug目录下创建一个i
- 过去的每一year,涌现出越来越多的Java框架。就像JavaScript,每个人都认为他们知道一个好的框架的功能应该是怎么样的。连我的老祖
- java "equals"和"==”异同首先简单说一下“equal”和“==”==操作对于基本数据类型比较的是
- 本文实例讲述了JavaWeb 网上书店 注册和登陆功能。分享给大家供大家参考,具体如下:工具:Eclipse + Navicat源码地址:h
- 一、概要我们可以用java实现简单的登录界面。如上效果,直观但也需要一步一步来完成,从界面弹窗的设置,图片的插入,文本框的设置,到登录的按钮
- 认证:验证当前访问系统的是不是本系统的用户,并且要确认具体是哪个用户授权:经过认证后判断当前用户是否有权限进行某个操作一、登录校验流程1、S
- 近期对两个应用进行改造,在上线过程中出现一系列问题(其中一部分是由于ObjectId误区导致的)先来了解下ObjectId:TimeStam
- 这篇实例中有四个类,分别为CacheItem 缓存实体类CachePool 缓存池Student 学生实
- 最近在用SpringMvc写项目的时候,遇到一个问题,就是方法的鉴权问题,这个问题弄了一天了终于解决了,下面看下解决方法项目需求:需要鉴权的
- 最近在做一个项目,遇到了项目打成 war 包的一个问题,项目创建时选择的时 jar 包方式,后因项目部署要求,需要打成 war 包部署,遇到
- 本文实例讲述了JAVA线程池原理。分享给大家供大家参考,具体如下:线程池的优点1、线程是稀缺资源,使用线程池可以减少创建和销毁线程的次数,每
- 让按钮拥有返回键的功能很简单,在点击事件加上finish();就OK了。如:public void onClick(View v){fini
- 尽管我们通常认为通过JAVA的反射机制来访问其它类的私有字段和私有方法是可行的,其实并没有那么困难。 注释:只有在单独的JAVA程序中运行该
- 一、垃圾回收机制创建对象就会占据内存,如果程序在执行过程中不能再使用某个对象,这个对象是徒耗内存的垃圾。作为程序员不用关心回收垃圾对象问题,