对于CPU长时间100%的问题,其实有一个比较标准的排查流程,现在模拟一个垃圾回收导致的cup占用率过高的排查方法。
步骤如下:
1.先通过top命令找到消耗cpu很高的进程id
在服务器上输入top,显示如下:
通过top命令定位到占用cpu过高的进程ID是2983。
2.根据进程找到消耗cpu很高的线程ID
在服务上输入top -p 2983,显示如下:
然后按一个大写的H,显示如下:
此时发现,按H之前,显示的Task,是进程的任务,按H之后显示的Threads,是线程的任务。
通过该方法找到了占用cpu过高的线程ID是2986和2985。
3.对当前进程做stack,输出所有的堆栈信息
在服务器上输入jstact 2983,显示如下:
此时会输出一大堆堆栈的信息,里面的nid就是线程号,只是它是十六进制的。
4.将第3步得到的线程ID转成16进制
将1进制的2986和2985进行转换为10进制,转换后为BA9和BAA。
5.根据得到16进制的线程ID找到堆栈的具体信息
6.解读堆栈信息,定位问题及代码位置
定位到ZWorker后,发现这其实是垃圾回收器里面的线程,这个问题的表现是cup占用时间长,其实内部是垃圾回收器在疯狂的进行工作导致cup占用率过高,本质上可能是发生了内存泄漏,或者就是程序在疯狂的进行垃圾回收,但是效率不是理想,导致cup占用过高。
总结:
通过jstack定位到对于的堆栈信息,一般会有两种问题,第一种是和垃圾回收相关(垃圾回收相关的线程),这个时候,就需要排查是不是系统出现了内存泄漏,或者是内存不足导致垃圾回收器在疯狂的工作,第二种可以定位到相关的线程信息,如果定位到线程信息,基本上就是跟代码有关系,比如说在多线程中使用HashMap,这个时候问题代码就可能定位到HashMap的put方法,因为多线程使用HashMap可能造成死循环问题,或者就是代码里面触发无限循环,所以也会定位到具体的代码。