什么是 Jstack
Jstack是Java虚拟机(JVM)的命令行工具,可用于生成Java应用程序的线程快照。它可以帮助开发人员诊断线程阻塞、死锁等问题。
使用Jstack的方法如下:
1.运行jstack命令,并将Java进程ID作为参数。例如:
jstack <pid>
其中,
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
执行后会卡住
打开一个新的页签,使用 top 命令 按 1,显示出多核CPU的使用情况,我这里是4核心的Cpu,所有有4个,可以看到 Cpu1 的用户内核的使用率达到了 100%,同时 第一个进程的 Cpu使用情况也是 100%,也就是有问题的 进程
top 命令界面下
进程pid为 20785
top 命令界面下,按 shift+h 切换成线程展示
线程id为 20800
但是通过 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
评论区