Java服務(wù),CPU 100%問題如何快速定位?
Java服務(wù),有時候會遇到CPU 100%的問題,對于這樣的問題,我們?nèi)绾慰焖俣ㄎ徊⒔鉀Q呢?一般會有如下三個步驟:
1、找到最耗CPU的進程
2、找到這個進程中最耗CPU的線程
3、查看堆棧信息,定位線程的什么操作消耗了大量CPU,定位對應(yīng)代碼
下面通過一個實例來詳解一下如何快速定位CPU問題
系統(tǒng):CentOS 7
模擬CPU占用偏高的測試代碼:
public class CpuUseTest {public static void main(String[] args) {new Thread() {public void run() {int result = 0;while (true) {result++;if (result > Integer.MAX_VALUE / 2) {result = 0;}}}}.start();}}
運行以上代碼后,通過以下幾步來查找CPU問題:
1、找到最耗CPU的進程
通過top命令查看進程的cpu占用情況,運行top命令后再鍵入P(大寫p),進程會按照CPU使用率排序,如下圖:

由上圖可以看到,最耗CPU的進程PID為2601,CPU使用率達到了100%
2、找到這個進程中最耗CPU的線程
可以使用top命令:
top -Hp ${進程的PID}也可以使用ps命令:
ps -mp ${進程的PID} -o THREAD,tid,time我們以top命令為例:
top -Hp 2601運行以上命令后再鍵入P(大寫p),線程會按照CPU使用率排序,如下圖:

可以看到進程2601的最耗CPU的線程PID為2611,CPU使用率達到了99.9%
3、查看堆棧信息,定位線程的什么操作消耗了大量CPU,定位對應(yīng)代碼
堆棧里,線程id是用16進制表示的,所以需要將線程PID轉(zhuǎn)化為16進制:
printf "%x\n" 2611輸出:
a33打印進程堆棧信息(注意2601是進程的PID),通過線程id,過濾得到線程堆棧:
jstack 2601 | grep a33 -A 20輸出信息如下:

由此可以看到,最耗CPU的代碼為CpuUseTest.java代碼中的第9行,也就是執(zhí)行無限循環(huán)的代碼塊所在的位置。
至此導致該應(yīng)用CPU偏高的問題,被成功定位。
4、查看堆棧信息中遇到的問題
剛開始查看堆棧信息的時候,使用了如下命令(請跟上面的命令對比一下,看看有什么不同):
jstack 2611 | grep a33 -A 20結(jié)果報錯:

是的,我把該寫進程PID的地方,寫成了線程PID,找了一圈,才解決這個問題,也耗費了不少時間。
