目 录CONTENT

文章目录

Jstack线上故障诊断实战:解决Java程序问题的技巧

小张的探险日记
2023-02-12 / 0 评论 / 0 点赞 / 402 阅读 / 2,639 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2023-02-13,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

什么是 Jstack

Jstack是Java虚拟机(JVM)的命令行工具,可用于生成Java应用程序的线程快照。它可以帮助开发人员诊断线程阻塞、死锁等问题。

使用Jstack的方法如下:

1.运行jstack命令,并将Java进程ID作为参数。例如:

jstack <pid>

其中,是您想生成快照的Java进程的ID。

2.Jstack命令将生成包含该进程的所有线程信息的快照,并输出到控制台。

3.可以使用任何文本编辑器打开生成的快照,以便更详细地检查线程状态和调用堆栈。

4.对于特定的问题,您可以分析快照并确定问题的根本原因。例如,如果您发现多个线程处于阻塞状态,则可以推断出存在死锁。

模拟线程问题Demo

环境:Centos:7,需要已经安装了Jdk。

安装命令:

[root@localhost home]# yum install java-1.8.0-openjdk.x86_64 -y
[root@localhost home]# yum install java-1.8.0-openjdk-devel.x86_64 -y

写一个 Java文件

在服务器上手写一个 java 文件

vi CpuExample.java

写入如下内容,空的while死循环,会拉高CPU

public class CpuExample extends Thread{

        public void run(){
                while(true){}
        }

        public static void main(String[] args){
                CpuExample ce = new CpuExample();
                ce.start();
        }

}

编译 Java文件

通过 javac 命令编译java文件生成class文件

[root@localhost home]# javac CpuExample.java

运行 class 运行

[root@localhost home]# java CpuExample

执行后会卡住

image.png

打开一个新的页签,使用 top 命令 按 1,显示出多核CPU的使用情况,我这里是4核心的Cpu,所有有4个,可以看到 Cpu1 的用户内核的使用率达到了 100%,同时 第一个进程的 Cpu使用情况也是 100%,也就是有问题的 进程

top 命令界面下
进程pid为 20785

image.png

top 命令界面下,按 shift+h 切换成线程展示
线程id为 20800

image.png

但是通过 jstack 生成的线程快照中线程的 id 为 16进制
所以需要转换一下,运行如下命令,得到线程id的16进制格式

[root@localhost ~]# printf "0x%x\n" 20800
0x5140

运行 jstack 进程id | grep -A 20 线程id(16进制),直接通过grep 过滤出有问题的线程信息并打印20行信息,也可以下载下来用文本工具打开,由信息可以看出是 CpuExample 的run方法报错,第4行,成功排查到问题点,接下来去改代码即可

[root@localhost ~]# jstack 20785 | grep -A 20 0x5140
"Thread-0" #9 prio=5 os_prio=0 tid=0x00007f0a60154000 nid=0x5140 runnable [0x00007f0a46bc2000]
   java.lang.Thread.State: RUNNABLE
        at CpuExample.run(CpuExample.java:4)

"Service Thread" #8 daemon prio=9 os_prio=0 tid=0x00007f0a60130800 nid=0x513e runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C1 CompilerThread2" #7 daemon prio=9 os_prio=0 tid=0x00007f0a60123800 nid=0x513d waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread1" #6 daemon prio=9 os_prio=0 tid=0x00007f0a60121800 nid=0x513c waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread0" #5 daemon prio=9 os_prio=0 tid=0x00007f0a6011f000 nid=0x513b waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Signal Dispatcher" #4 daemon prio=9 os_prio=0 tid=0x00007f0a60110800 nid=0x513a runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007f0a600e4800 nid=0x5139 in Object.wait() [0x00007f0a476f5000]
   java.lang.Thread.State: WAITING (on object monitor)

Jstack还提供了一些其他选项,可以帮助您更详细地诊断问题。以下是一些常见的选项:

-F:强制执行Jstack,即使Java进程正在运行。

-m:生成带有本地方法信息的快照。

-l:生成详细的快照,包括线程ID、线程状态、锁信息等。

-v:生成详细的快照,包括线程ID、线程状态、锁信息、调用堆栈等。

-h:查看帮助信息,了解更多关于Jstack命令的选项。

例如,如果您希望生成带有本地方法信息和详细锁信息的快照,则可以使用以下命令:

jstack -m -l <pid>

请注意,使用不同的选项可能会影响生成的快照的详细程度和大小。因此,请确保您选择适合您需求的选项。

如果您希望生成带有本地方法信息的快照并将其输出到文件中,则可以使用以下命令:

jstack -m -o <pid> > jstack.out

0

评论区