获取Java线程转储的常用方法
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
下面请看具体的演示:
# 1. 查看帮助信息jstack -help12
输出的内容类似于:
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 message123456789101112131415
对应的参数选项是可选的。 具体含义如下:
-F
选项, 强制执行线程转储; 有时候jstack pid
会假死, 则可以加上-F
标志-l
选项, 会查找堆内存中拥有的同步器以及资源锁-m
选项, 额外打印 native栈帧(C和C++的)
例如, 获取线程转储并将结果输出到文件:
jstack -F 17264 > /tmp/threaddump.txt1
使用 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.print1
2.5 jconsole
jconsole 工具也可以查看线程栈跟踪。
打开jconsole并连接到正在运行的Java进程, 导航到“线程”选项卡, 可以查看每个线程的堆栈跟踪:
2.6 小结
事实证明, 可以使用JDK中的很多工具来获取线程转储。 让我们回顾一下, 并总结它们的优缺点:
jstack
:获取线程转储最简单最方便的工具; Java 8之后可以使用 jcmd 工具来替代;jmc
:增强的JDK性能分析和问题诊断工具。 用这款工具进行性能分析的开销非常低。jvisualvm
:轻量级的开源分析工具, 图形界面非常棒, 还支持各种强悍的功能插件。jcmd
: 非常强大的本地工具, 支持Java 8及更高版本。 集成了多种工具的作用, 例如: 捕获线程转储(jstack), 堆转储(jmap), 查看系统属性和查看命令行参数(jinfo)jconsole
:也可以用来查看线程栈跟踪信息。
3. 使用Linux命令
在企业应用服务器中, 出于安全原因, 可能只安装了 JRE。 这时候没法使用这些JDK内置的工具。
但还是有办法获取线程转储。
3.1 使用 kill -3
指令
在Unix/Linux之类的系统中, 可以使用 kill
命令获取线程转储, 底层实现原理, 则是通过系统调用 kill()
将信号参数发送给进程。 这里需要发送的是 -3
信号。
一般先通过 jps
找到JAVA进程对应的pid, kill -3
使用示例如下:
kill -3 172641
3.2 Ctrl + 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();}12345678
上面代码做的事情很简单, 先通过 ManagementFactory
获取 ThreadMxBean
对象。
方法的布尔参数 lockedMonitors
和 lockedSynchronizers
, 表示是否导出持有的同步器和管程锁。
5. 总结
我们通过具体示例展示了获取线程转储的各种方法。
首先介绍的是各种JDK内置工具,
然后讨论了命令行方式,
最后介绍了JMX编程的方式。
完整的示例代码请参考 GitHub仓库 。
获取Java线程转储的常用方法的更多相关文章
- Java 线程转储 [转]
http://www.oschina.net/translate/java-thread-dump java线程转储 java的线程转储可以被定义为JVM中在某一个给定的时刻运行的所有线程的快照.一个 ...
- Java 线程转储
软件维护是一个枯燥而又有挑战性的工作.只要软件功能符合预期,那么这个工作就是好的.设想一个这样的情景,你的电话半夜也一直在响(这不是一个令人愉快的感受,是吧?)任何软件系统,无论它当初是被设计的多好, ...
- Java 线程创建与常用方法
进程与线程 进程 程序由指令和数据组成,但这些指令要运行,数据要读写,就必须将指令加载至 CPU,数据加载至内存.在指令运行过程中还需要用到磁盘.网络等设备.进程就是用来加载指令.管理内存.管理 IO ...
- 获取Java线程返回值的几种方式
在实际开发过程中,我们有时候会遇到主线程调用子线程,要等待子线程返回的结果来进行下一步动作的业务. 那么怎么获取子线程返回的值呢,我这里总结了三种方式: 主线程等待. Join方法等待. 实现Call ...
- Java 死锁诊断 -- 线程转储
java线程转储 java的线程转储可以被定义为JVM中在某一个给定的时刻运行的所有线程的快照.一个线程转储可能包含一个单独的线程或者多个线程.在多线程环境中,比如J2EE应用服务器,将会有许多线程和 ...
- 【JAVA并发第二篇】Java线程的创建与运行,线程状态与常用方法
1.线程的创建与运行 (1).继承或直接使用Thread类 继承Thread类创建线程: /** * 主类 */ public class ThreadTest { public static voi ...
- Java并发之线程转储
一.java线程转储 java的线程转储可以被定义为JVM中在某一个给定的时刻运行的所有线程的快照.一个线程转储可能包含一个单独的线程或者多个线程.在多线程环境中,比如J2EE应用服务器,将会有许多线 ...
- java线程面试
1) 什么是线程? 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位.程序员可以通过它进行多处理器编程,你可以使用多线程对运算密集型任务提速.比如,如果一个线程完成 ...
- Java线程与多线程教程
本文由 ImportNew - liken 翻译自 Journaldev. Java线程是执行某些任务的轻量级进程.Java通过Thread类提供多线程支持,应用可以创建并发执行的多个线程. 应用 ...
随机推荐
- 用 Java 训练出一只“不死鸟”
作者:Kingyu & Lanking FlappyBird 是 2013 年推出的一款手机游戏,因其简单的玩法但极度困难的设定迅速走红全网.随着深度学习(DL)与增强学习(RL)等前沿算法的 ...
- 用Python批量爬取优质ip代理
前言 有时候爬的次数太多时ip容易被禁,所以需要ip代理的帮助.今天爬的思路是:到云代理获取大量ip代理,逐个检测,将超时不可用的代理排除,留下优质的ip代理. 一.爬虫分析 首先看看今天要爬取的网址 ...
- 分析《令人心动的offer2》网友们都在吐槽什么?
综艺,是我们劳累了一天的放松方式,也是我们饭后的谈资.看着自己喜欢的综艺,时光足够美.而<令人心动的offer >,就是一个不错的综艺选择.有人说它让自己更自卑了,而我觉得挺有意思. &l ...
- DotNet .Net Framework与Net Core与Net Standard 以及.NET5
Net Framework 是什么 1.Net Framework 是Net的一种实现,在此类库上我们可以使用C#,VB,F#进行程序编写,主要用于构建Windows 下的应用程序 2.有两部分组成部 ...
- 2021年第一个flag
2021年开始更新本文列出的系列文章,根据书籍和自己的理解整理出spring框架的相关的学习 Spring 的设计理念和整体架构 学习目标 Spring的各个子项目 Spring的设计目标 Sprin ...
- 拥抱 C/C++ : Android JNI 的使用
编译工具 CMake 以及 Android 上 JNI 的使用介绍. 编译工具 CMake 在Android Studio 2.2 之后,工具中增加了 CMake 的支持,于是我们有两种选择来编译 c ...
- java并发包工具(java.util.Concurrent)
一.CyclicBarrier 作用:所有线程准备好才进行,只要一条线程没准备好,都不进行 用法:所有线程准备好以后调用CyclicBarrier的await方法,然后主线程执行CyclicBarri ...
- 认识PHP8
PHP 团队于2020年11月26日宣布 PHP 8 正式发布!这意味着将不会有 PHP 7.5 版本.PHP8 目前正处于非常活跃的开发阶段,所以在接下来的几个月里,情况可能会发生很大的变化.我也分 ...
- 风炫安全web安全学习第三十七节课 15种上传漏洞讲解(二)
风炫安全web安全学习第三十七节课 15种上传漏洞讲解(二) 05后缀名黑名单校验之上传.htaccess绕过 还是使用黑名单,禁止上传所有web容器能解析的脚本文件的后缀 $is_upload = ...
- CS系统中分页控件的制作
需求:在一个已有的CS项目(ERP中),给所有的列表加上分页功能. 分页的几个概念: 总记录数 totalCount (只有知道了总记录数,才知道有多少页) 每页记录数 pageSize (根据总 ...