1

获取Java线程转储的常用方法

 2 years ago
source link: https://blog.csdn.net/renfufei/article/details/112339222
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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:获取线程转储最简单最方便的工具; 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 17264

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();
}

上面代码做的事情很简单, 先通过 ManagementFactory 获取 ThreadMxBean 对象。
方法的布尔参数 lockedMonitorslockedSynchronizers, 表示是否导出持有的同步器和管程锁。

我们通过具体示例展示了获取线程转储的各种方法。

首先介绍的是各种JDK内置工具,
然后讨论了命令行方式,
最后介绍了JMX编程的方式。

完整的示例代码请参考 GitHub仓库

原文链接:

https://www.baeldung.com/java-thread-dump


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK