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循环的位置。

Guess you like

Origin blog.csdn.net/feinifi/article/details/120746488