# JStack 线程转储分析器

> 原文： [https://howtodoinjava.com/linux/how-to-get-thread-dump-in-linux-using-jstack/](https://howtodoinjava.com/linux/how-to-get-thread-dump-in-linux-using-jstack/)

线程转储是 Java 虚拟机（JVM）中当前活动的所有 Java 线程的列表。 有几种方法可以从 JVM 提取[线程](https://howtodoinjava.com/java/multi-threading/java-thread-life-cycle-and-thread-states/)转储。 强烈建议在分析任何问题（例如[死锁](https://howtodoinjava.com/java/multi-threading/writing-a-deadlock-and-resolving-in-java/)或资源使用情况分析）时采取多个线程转储。 最好在多个线程转储中进行确认，然后单次尝试得出结论。

## 1.获取 Java 进程的 PID

获得线程转储所需的第一条信息是 Java 进程的 PID。

Java JDK 附带`jps`命令，该命令列出了所有 Java 进程 ID。 您可以这样运行此命令：

```java
$ jps -l
```

***记住*** – 您可能必须以`$ sudo -u jps -l`运行此命令，其中“`user`”是正在运行的 Java 进程用户的用户名。

即使现在，如果您仍无法找到进程 ID，请使用以下命令：

```java
$ ps -aef | grep java
```

## 2.从 JVM 请求线程转储

如果已安装/可用，我们建议使用 [**jstack**](https://docs.oracle.com/javase/1.5.0/docs/tooldocs/share/jstack.html "jstack") 工具。 它将线程转储打印到命令行控制台。

要使用 jstack 获得**线程转储**，请运行以下命令：

```java
$ jstack
```

您可以使用控制台输出`redirect/append`伪指令将连续的线程转储输出到文件中：

```java
$ jstack  >> threaddumps.log
```

**要点**

1.  从 JDK 1.5 开始，可以使用 jstack 工具。
2.  即使启用了`-Xrs jvm`参数，jstack 也可以工作。
3.  无法使用 JDK 1.6 中的 jstack 工具从运行在 JDK 1.5 上的进程中进行线程转储。

## 3.使用 jstack 脚本以固定的时间间隔进行线程转储采样

这个简单的 Shell 脚本以固定的时间间隔拍摄了几个 jstack 快照（[参考文档](https://wiki.eclipse.org/How_to_report_a_deadlock#jstackSeries_--_jstack_sampling_in_fixed_time_intervals_.28tested_on_Linux.29 "jstack refernce")）：
```java
#!/bin/bash

if [ $# -eq 0 ]; then
    echo >= 2 "Usage: jstackSeries  [ count [ delay ] ]"
    echo >= 2 "    Defaults: count = 10, delay = 1 (seconds)"
    exit 1
fi

pid=$1          # required
count=${2:-10}  # defaults to 10 times
delay=${3:-1} # defaults to 1 second

while [ $count -gt 0 ]
do
    jstack $pid >jstack.$pid.$(date +%H%M%S.%N)
    sleep $delay
    let count--
    echo -n "."
done

```

像这样使用上面的脚本：

```java
$ jstackSeries  10 5
```

## 4.如何比较两个 JStack 线程转储

要**比较线程转储**，您可以使用交互式差异查看器，例如：

```java
$ vimdiff file1 file2 file3 file4 # up to 4 files
```

查看 jstack 跟踪的哪些部分随时间变化的另一种方法是使用`$ context diff`（-c 选项）比较相邻的 jstack 跟踪：

```java
d_old=""
for d in jstack.13585.12171*
do
  if [ -n "$d_old" ]
  then
    diff -c "$d_old" "$d"
  fi
  d_old="$d"
done

```

在这里，结果仅显示 **JStack 线程转储**在文件之间更改的位置。

学习愉快！