持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第14天,点击查看活动详情
前一篇文章讲解了jinfo命令,用来查看关于jvm相关信息。本章我们来学习下
jstack命令,看看它能帮助我们解决那些JVM的问题。
什么是线程转储?
在前面讲解的jmap一文当中,我们还介绍了什么是堆转储文件。而本章学习的jstack,将会向大家介绍一下什么是线程转储信息。
线程转储(Thread Dump),就是jvm当中线程的状态的一次快照信息。学习过java的应该都知道线程包含多种状态,可以参考下面这篇文章:java并发编程(三)java线程状态与方法。
通常我们会将线程转储文件保存到文本文件中,可以直接查看,或通过api查看。内部包含了线程的行为,对于排查问题非常的有用。
jstack
jstack用来转储java进程的栈信息。
通过帮助文档查看其使用方式:
[root@hecs-402944 ~]# 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
如上所示的三种使用方式,我们只关注第一种:
jstack [-l] <pid>
下面分别看下几个参数什么含义:
-F强制线程转储。当jstack pid线程没有响应的时候。-m打印java进程信息和native信息(C++,本地方法栈)-l打印同步器和锁的相关信息。
我们在使用的时候不会直接让它在控制台直接输出,而是生成txt文件,使用> xxx.txt的方式。
获取线程pid:
[root@hecs-402944 opt]# jps
21203 jar
5494 Jps
强制输出
jstack -F 21203 > 21203.txt
此时生成了文件21203.txt在当前文件夹:
打开看看:
如上所示可以看到所有线程的状态,和此线程栈的调用。还包括死锁deadlock的信息,只不过当前服务没有死锁存在。
打印native的信息
jstack -F -m 21203 > 21203-native.txt
如下所示,仍然有输出内容,但是具体的展示方式是不同的,但是同样包含线程的状态和调用栈,以及死锁信息:
打印同步器和锁信息
jstack -F -l 21203 > 21203-locks.txt
能够明显感觉到,导出此类信息,耗时增加。目测应该会导致应用暂停,发生gc操作,所以生产还是慎用。
打开看看内容,增加了同步器相关内容:
jstack使用方式
前面已经介绍了如何使用了,为何又有一个使用方式的小章节?
本小节将会介绍在实际环境中如何使用jstack去发现问题,建议收藏。
-
假设我们发现服务器的CPU飙高,那么可以按照如下的步骤去操作:
-
top命令,找到占用CPU高的进程(举例一个进程:PID-1)。
-
top -Hp PID-1 查看进程下的线程占用cpu情况(举例该命令查到的线程PID-2)。
-
将线程PID2转换为16进制:
printf "%x\n" PID-2(堆栈中,线程id是以16进制存储的) -
使用jstack -l PID-1 >jvm_listlock.txt输出dump信息到堆栈。用步骤3中的16进制id去找到存在问题的代码行。
-
注意:上述步骤不适用于openjdk,因为本文使用的是openjdk,上面的图示都可以返现,线程的id并非是16进制,直接可以通过PID-2进行查询。
总结
本文介绍了jstack的使用和实际场景如何发现问题,对于我们日常工作当中分析问题,效果还是很明显的。
需要注意的是,导出线程转出文件是还是会对服务器产生性能影响,生产环境慎重使用。