JVM - jstack工具

2021/07/29 JVM 共 1522 字,约 5 分钟
Bob.Zhu

jstack是JDK中自带的Java工具之一,用于生成虚拟机当前时刻的线程快照,含有正在执行的方法堆栈的集合信息, 生成线程快照的主要目的是定位线程出现长时间停顿的原因, 如线程间死锁、死循环、请求外部资源导致的长时间等待等问题。

命令和参数

通过 jstack -h命令可以查看可选参数,主要有三个:

  • -l:除堆栈外,显示关于锁的附加信息,在发生死锁时可以用jstack -l pid来观察锁持有情况
  • -F:当正常输出的请求不被响应时,强制输出线程堆栈
  • -m:如果调用到本地方法的话,可以显示C/C++的堆栈
$ jstack -h
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

知识回顾

线程状态

线程状态

  • New:创建后尚未启动的线程处于这种状态,不会出现在Dump中。
  • RUNNABLE:包括Running和Ready。线程开启start()方法,会进入该状态,在虚拟机内执行的。
  • Waiting:无限的等待另一个线程的特定操作。
  • Timed Waiting:有时限的等待另一个线程的特定操作。
  • Blocked:在程序等待进入同步区域的时候,线程将进入阻塞状态,在等待监视器锁。
  • Terminated:已终止线程的线程状态,线程已经结束执行。

Dump文件的线程状态一般其实就以下3种:

  • RUNNABLE,线程处于执行中
  • BLOCKED,线程被阻塞
  • WAITING,线程正在等待

Monitor 监视锁

因为Java程序一般都是多线程运行的,Java多线程跟监视锁环环相扣,所以我们分析线程状态时,也需要回顾一下Monitor监视锁知识。 Monitor的工作原理图如下:

线程状态

  • 线程想要获取monitor,首先会进入Entry Set队列,它是Waiting Thread,线程状态是Waiting for monitor entry。
  • 当某个线程成功获取对象的monitor后,进入Owner区域,它就是Active Thread。
  • 如果线程调用了wait()方法,则会进入Wait Set队列,它会释放monitor锁,它也是Waiting Thread,线程状态in Object.wait()
  • 如果其他线程调用 notify() / notifyAll() ,会唤醒Wait Set中的某个线程,该线程再次尝试获取monitor锁,成功即进入Owner区域。

案例分析

死锁问题

排查Java死锁步骤:

  1. jps
  2. jstack -l pid
  3. 分析堆栈信息

CPU过高问题

分析CPU过高步骤:

  1. top
  2. top -Hp pid
  3. jstack pid
  4. jstack -l pid >/tmp/log.txt
  5. 分析堆栈信息

参考资料

文档信息

Search

    Table of Contents