jstat使用详解

jstack 是用于生成 Java 进程线程快照(thread dump)的工具,通常用于分析线程状态、排查死锁、线程阻塞、CPU 占用高等问题。线程快照可以显示 JVM 内部所有线程的执行情况,包括线程的调用栈、状态等。以下是 jstack 的详细使用指南:

基本用法

jstack [options] <pid>
  • pid: Java 进程的进程号。可以通过 jpsps 或者其他系统工具查看。

常用选项

  1. -F
    当普通 jstack 命令无法连接到 JVM 时强制生成线程快照。使用该选项可能会终止目标 JVM。

    jstack -F <pid>
    
  2. -l
    显示锁的附加信息,包括当前线程持有的锁以及等待的锁。

    jstack -l <pid>
    
  3. -m
    显示混合模式的线程堆栈,即 Java 调用栈和本地 C/C++ 代码栈。如果你怀疑本地方法(如 JNI 调用)可能导致了问题,可以使用此选项。

    jstack -m <pid>
    
  4. -h
    显示帮助信息。

典型输出分析

jstack 的输出显示了每个线程的状态、调用栈及相关信息。典型的线程快照格式如下:

"main" #1 prio=5 os_prio=0 tid=0x00007fabc400b000 nid=0x5a6f runnable [0x00007fab5bffb000]
   java.lang.Thread.State: RUNNABLE
        at com.example.MyClass.myMethod(MyClass.java:123)
        at java.lang.Thread.run(Thread.java:748)
  • 线程名称: main 是线程名称,#1 是线程 ID,prio=5 是线程的优先级。
  • os_priotid/nid: os_prio 是操作系统中的线程优先级,tid 是 Java 层的线程 ID,nid 是操作系统层面的线程 ID。
  • 线程状态: 线程状态可以是 RUNNABLE(可运行的)、WAITING(等待状态)、TIMED_WAITING(超时等待)或 BLOCKED(被其他线程阻塞)。
  • 调用栈: 显示当前线程的调用栈,通常从 Java 方法开始。如果线程正在执行本地代码,也可能显示本地方法。

常见线程状态

  1. RUNNABLE
    线程在运行或等待 CPU 时间片。高 CPU 占用时,多个 RUNNABLE 线程可能正在竞争资源。

  2. WAITING (on object monitor)
    线程在等待某个对象的锁或条件变量的通知(通过 Object.wait())。这种线程通常在等待其他线程释放资源。

  3. TIMED_WAITING (on object monitor)
    WAITING 类似,但等待是有超时时间的(如 Thread.sleep()Object.wait(timeout))。

  4. BLOCKED (on object monitor)
    线程在试图进入同步代码块时被阻塞,等待获取一个对象的锁。

  5. TIMED_WAITING (sleeping)
    线程正在睡眠(通过 Thread.sleep())。

常见场景下的 jstack 使用

1. 高 CPU 占用问题

当某个 Java 进程的 CPU 使用率异常高时,可以使用 jstack 生成线程快照,查看哪些线程处于 RUNNABLE 状态并消耗 CPU 资源。
步骤:

  1. 通过 topps 命令找到高 CPU 占用的 Java 进程 PID。
  2. 执行 jstack 命令:
    jstack -l <pid> > thread_dump.txt
    
  3. 在输出中寻找处于 RUNNABLE 状态的线程,分析它们的调用栈,找到导致高 CPU 的原因。
2. 死锁问题

当怀疑出现死锁时,使用 jstack 可以直接检测死锁并输出相关信息。线程快照会显示哪些线程持有锁并等待其他线程释放锁。

jstack -l <pid> > thread_dump.txt

输出示例:

Found one Java-level deadlock:
=============================
"Thread-1":
  waiting to lock Monitor@0x00000000d611c5c8, which is held by "Thread-2"
"Thread-2":
  waiting to lock Monitor@0x00000000d611c3c8, which is held by "Thread-1"

上面的输出表明线程 1 和线程 2 出现了循环依赖,导致死锁。

3. 线程阻塞或响应变慢

当某个 Java 应用程序响应变慢或卡住时,使用 jstack 可以查看线程是否处于 BLOCKEDWAITING 状态,分析阻塞的原因。
步骤:

  1. 执行 jstack,将输出保存到文件:
    jstack -l <pid> > thread_dump.txt
    
  2. 查找 BLOCKEDWAITING 状态的线程,分析调用栈,查明阻塞源头。
4. Full GC 问题

当频繁发生 Full GC 时,应用程序可能会长时间停顿,使用 jstack 可以查看 Full GC 期间线程的状态。

自动获取线程快照

可以设置脚本在某些条件下(如 CPU 使用率超过某个阈值)自动生成 jstack,例如:

#!/bin/bash
pid=$1
cpu_usage=$(top -b -n1 -p $pid | grep $pid | awk '{print $9}')
if (( $(echo "$cpu_usage > 80.0" |bc -l) )); then
   jstack -l $pid > /tmp/thread_dump_$pid.txt
fi

这个脚本可以每隔几秒运行一次,当某个 Java 进程的 CPU 使用率超过 80% 时自动生成线程快照。

jstack 的限制

  • 内存使用高时可能无法生成快照:当 JVM 内存使用率过高,生成线程快照可能会失败。
  • 强制生成线程快照可能影响 JVM 性能:使用 -F 选项强制生成线程快照时,可能导致 JVM 暂时挂起,甚至崩溃。

通过 jstack 工具,可以较为详细地分析 Java 应用程序中线程的状态,定位 CPU 占用、死锁、线程阻塞等问题,是 Java 性能调优和问题排查的必备工具。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

测试不打烊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值