Jstack 用于打印出给定的 java 进程 ID 或 core file 或远程调试服务的 Java 堆栈信息.

Prints Java thread stack traces for a Java process, core file, or remote debug server. This command is experimental and unsupported.

如果 java 程序崩溃生成 core 文件,jstack 工具可以用来获得 core 文件的 java stack 和 native stack 的信息,从而可以轻松地知道 java 程序是如何崩溃和在程序何处发生问题。另外,jstack 工具还可以附属到正在运行的 java 程序中,看到当时运行的 java 程序的 java stack 和native stack 的信息, 如果运行的 java 程序呈现 hung 的状态,jstack 是非常有用的。

thread dump 就是将当前时刻正在运行的 JVM 的线程拷贝一份,可以用来分析程序执行情况。

用法

打印某个进程的堆栈信息

jstack [PID]

jstack -l [PID]
jstack -m [PID]

关于如何找到PID,有很多方法,使用 jps -v 或者 ps -aux 或者 htop 等等方法都可以。

分析

在执行 jstack -l [PID] > /tmp/output.txt 之后可以对 /tmp/output.txt 进行分析

开头交代当前 dump 的时间和 JVM 基本信息

2018-05-24 14:41:06
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.101-b13 mixed mode):

接下来就是程序的线程信息

"resin-8015" #8015 daemon prio=5 os_prio=0 tid=0x00007f991820a800 nid=0x25e65 waiting on condition [0x00007f96b1b39000]
   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:304)
        at com.caucho.env.thread2.ResinThread2.park(ResinThread2.java:196)
        at com.caucho.env.thread2.ResinThread2.runTasks(ResinThread2.java:147)
        at com.caucho.env.thread2.ResinThread2.run(ResinThread2.java:118)

   Locked ownable synchronizers:
        - None

线程的状态 Thread Life States

  • alive 通常运行时状态
  • not started 线程已经被 java.lang.Thread.start() 请求运行,但是实际上操作系统还没有开始
  • terminated 线程已经结束 run() 并且通知其他线程 joining

线程运行状态 Thread Run States

  • blocked 该线程尝试进入一个被其他线程占用的 synchronized 块,当前线程直到锁被释放之前一直都是 blocked 状态
  • blocked (on thin lock) 和 blocked 相同的状态,但是锁需要是 thin lock
  • waiting 当前线程调用了对象的 Object.wait() ,当前线程会保持该状态直到其他线程发送通知到该对象
  • sleeping 当前线程调用了 java.lang.Thread.sleep()
  • parked 当前线程调用了 java.util.concurrent.locks.LockSupport.park()
  • suspended 当前线程的执行被 java.lang.Thread.suspend() 暂停,或者有 JVMTI/JVMPI agent 调用

以上内容来自 Oracle

通过 jstack 信息可以分析线程死锁,或者系统瓶颈,但是这篇文章比较粗浅,只介绍了大概,等以后熟悉了补上。

reference