JVM定位问题之jstack使用

背景

本人在刚开始接触企业级开发的时候,就曾经写过一段类似于死循环的代码。然后把这个代码发布到线上,Grafana显示该应用上线后CPU一直接近100%,于是在大佬的帮助下用jstack定位到问题并且解决了,所以总结一下jstack的使用吧。

jstack描述

此命令是为Java进程或核心文件或远程调试服务器打印Java线程的堆栈跟踪。jstack可以同时打印所有线程的Java和本机栈帧。jstack常用于定位线程的死循环、死锁等情况。

场景模拟

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package JVM;

import java.util.ArrayList;
import java.util.List;

/**
* Jstack演示
*
* @author god-jiang
* @date 2021/5/3 15:00
*/
public class JstackDemo {
public static void main(String[] args) {
// 死循环
List<Integer> list = new ArrayList<Integer>() {
{
add(666);
}
};
System.out.println("开始无限读数据");
while (true) {
list.get(0);
}
}
}

当运行以上的程序,由于出现了死循环,往往表现出来的时候是CPU100%,这个时候我们应该进去服务器,用top命令查找出CPU占用率最高的进程pid。

img

用top命令发现了CPU占用率最高的pid为1639,这个时候就要用top -H -p 1639去该进程里面查看各个线程的情况,找到线程占用率最高的nid。(由于博主用的是mac电脑,没有top -H命令,所以就不演示这一步了~~~)

可以用jps查出目前正在运行的Java进程,知道1639对应的是JstackDemo这个java进程

img

然后可以用jstack pid来分析线程的堆栈情况

img

可以发现nid=0xe03线程出现了等待,初步判断为死循环。(WAITING一般为死循环,BLOCKED一般为死锁),看到是JstackDemo的22行出问题,所以去程序找到对应的行数分析。

img

最后定位到这里,发现是死循环引起的,根据不同的场景和情况去解决即可。

重点归纳

发现CPU100%的解决思路大致可以分为以下:

  1. 用top查出CPU占用率高的进程pid
  2. 用jps大致确定pid是对应线上的哪个进程导致的
  3. 用top -H -p pid找到该pid下线程占用率最高的线程nid,此时nid是10进制
  4. 用jstack pid | grep nid查出对应的堆栈情况,这里要注意nid是要转换为16进制
  5. 根据WAITING或者BLOCKED大致判断是死循环还是死锁,然后回到程序中定位代码并且根据业务场景解决

总结

根据本人在企业开发遇到的一次线上CPU100%的事故,然后引起对Jstack的学习,知道jstack的作用还有对线上问题排查和定位的过程。希望以上分享对Java程序员有所帮助。

-------------本文结束感谢您的阅读-------------

本文标题:JVM定位问题之jstack使用

文章作者:god-jiang

发布时间:2021年05月03日 - 15:45:27

最后更新:2021年05月03日 - 15:51:11

原始链接:https://god-jiang.github.io/2021/05/03/JVM定位问题之jstack使用/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

创作不易,您的支持就是我坚持的动力,谢谢大家!
0%