jstack常用命令

139 阅读3分钟

jstack 命令是 Java 虚拟机(JVM)自带的诊断工具之一,主要用于生成 JVM 当前时刻的线程快照(Thread Dump)

线程快照包含了虚拟机中每一条线程正在执行的方法堆栈的集合。生成线程快照的主要目的是帮助定位线程出现长时间停顿的原因,例如线程间死锁、死循环、请求外部资源导致的长时间等待等问题。

📌 jstack 命令的基本语法

最基本的用法是指定一个运行中的 Java 进程 ID(PID):

jstack [options] <pid>

或者分析一个 core dump 文件:

jstack [options] <executable> <core file>

✨ 常用参数选项详解

jstack 命令提供了一些非常有用的参数,可以帮助你获取更详细或在特殊情况下强制获取线程信息:

参数描述作用和应用场景
无选项默认输出打印指定 Java 进程的线程堆栈信息。
-l长格式(long listing)最常用的选项之一。 除了堆栈信息外,还会显示关于锁(java.util.concurrent 相关的 OwnableSynchronizer)的附加详细信息,如锁的持有者和等待者。这对于诊断死锁和与锁相关的性能问题至关重要。
-m混合模式(mixed mode)打印 Java 帧本地 C/C++ 帧的混合信息。当 Java 代码通过 JNI 调用了本地(Native)方法时,这个选项可以帮助你了解 Java 代码与本地代码之间的交互情况。
-F强制模式(force)当目标 Java 进程不响应(例如进程已挂起或处于某种僵死状态)时,强制输出线程堆栈。在使用时应格外小心,因为强制打印可能会对目标进程产生影响。
-h-help帮助信息打印 jstack 命令的帮助信息。

示例

  • 诊断死锁(推荐):(<pid> Java 进程 ID)

    jstack -l <pid>
    
  • 目标进程无响应时:

    jstack -F <pid>
    

💡 线程快照中需要关注的状态

在 jstack 输出的线程快照中,你需要重点关注 Java 线程的几种状态:

线程状态描述关注点/含义
RUNNABLE线程正在执行或在等待 CPU 调度。如果一个线程长时间处于此状态且 CPU 占用率高,可能存在死循环。
BLOCKED线程在等待进入同步区域(即等待获取 监视器锁/内置锁)。输出中通常显示为 waiting for monitor entry。这是分析锁竞争的重点。
WAITING线程无限期地等待另一个线程的特定操作(如 Object.wait()Thread.join()LockSupport.park())。输出中可能显示为 parkingin Object.wait() 。需要找到唤醒它的线程或操作。
TIMED_WAITING线程有时限地等待另一个线程的特定操作(如 Thread.sleep()Object.wait(timeout)LockSupport.parkNanos())。通常是正常的,但在分析性能问题时,如果大量线程长时间处于这种状态,可能意味着请求外部资源(如网络IO)耗时过长

重点关注的输出信息

  • waiting for monitor entry:线程正在等待获取一个对象的内置锁(moniter),通常是进入一个同步块或同步方法时。
  • waiting on conditionparking:线程在等待一个条件或资源,例如使用了 java.util.concurrent 包中的锁或条件变量。
  • Locked xxx:线程已经持有的锁。在 -l 模式下可以更清晰地看到。