jstack排查java进程占用cpu过高示例
Posted luffy5459
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jstack排查java进程占用cpu过高示例相关的知识,希望对你有一定的参考价值。
java程序开发阶段,我们都是在本地调试,基本不会出现cpu占用过高。
一旦程序部署到了线上,问题可能随着时间的推移,慢慢暴露,而且当你追查源码的时候,却无法复现。这时候很懊恼,其实我也一直很懊恼。面试的时候,还被问过这个问题,我说一般是通过jstack排查,面试官说还有没有别的办法,我没说上来,后来我问他,他们生产环境的排查使用什么办法,他也好像不是很懂,简单说了一个词语:火焰图。我后来还特意查了,没找到相关资料。
言归正传,jstack,确实可以定位cpu占用过高的问题。
大体步骤网上都给出了很多,大致如下:
1、top -c //定位Java进程。
2、top -Hp pid //获得该进程下占用时间最多的进程id。
3、printf "%x\\n" tid //打印线程号对应的16进制表示,也可以通过其他方式计算。
4、jstack -l pid | grep hex(tid) -A 10 //过滤关键字之后10行的内容。
下面通过具体实验演示这个步骤。
我们不妨写一个故意让程序进入死循环的的程序:
public class Test{
public static void main(String args[]){
System.out.println("start.");
boolean flag = false;
while(!flag){
}
System.out.println("end.");
}
}
接着,在linux服务器上,编译运行,因为是死循环,程序进程占用cpu过高通过top很容易辨认。
top -c
找到Test程序的进程号pid->4309
接着,我们要通过4309找到这个进程关联详细进程。
top -Hp 4309
这个按照TIME+指标最长的那个来查找,这里找到的是4310。
这个数字是10进制的,在内存中,都是通过16进制表示进程号,所以这里要通过linux命令来获取他的16进制表示,你也可以通过其他方式计算16进制。这里计算出来的是 10d6
接着,我们通过jstack -l pid来查询Test程序运行的堆栈日志。并通过关键字 10d6 匹配,找到关联的java程序具体位置。
printf "%x\\n" 4310
jstack -l 4309 | grep 10d6 -A 10
以上jstack命令结合grep查找命令精确找到了进程ID为4310 (16进制10d6)进程耗时的代码在Test程序的第5行。
使用jstack命令,我们需要知道进程ID,所以这里的4309就是最开始通过top -c命令找到的那个进程ID,而10d6是耗时进程4310的16进制表示。所以这里我们要搞清楚两个ID的含义。
我们可以查看Test程序的代码:
第5行,正好是我们while循环的位置。
以上是关于jstack排查java进程占用cpu过高示例的主要内容,如果未能解决你的问题,请参考以下文章