如何處理Java應用在CPU高時的問題排查與解決
在Tomcat的應用下,出現Java進程佔用非常高的CPU,而內存卻佔用很少時,就需要考慮是否程序中有線程死鎖的情況出現,造成了CPU資源無法釋放;這時就要通過對CPU的線程及進程進行分析來找到問題的原因;
查找與定位問題通常分爲以下幾步:
1. 確定當前Java的進程ID:
ps -ef|grep java得到當前運行的java進程的PID;
如得到的ID爲10000
2.找到Java線程後,需要再定位實際在CPU中運行的線程情況,我們知識進程是表明一個程序,而線程是程序中實際在CPU中進行時間片的運算,因此我們需要定位到實際的線程情況:
方法一:ps -mp 10000 -o THREAD,tid,time | sort -rn
顯示結果如:
USER %CPU PRI SCNT WCHAN USER SYSTEM TID TIME
root 98.5 19 - - - - 10001 00:35:48
root 90.1 19 - - - - 10102 00:20:16
...
方法二:top -Hp 10000 -d 1 -n 3
顯示結果如:
top - 23:37:41 up 1:17, 4 users, load average: 0.09, 0.08, 0.12
Threads: 7 total, 0 running, 7 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.5 us, 0.0 sy, 0.0 ni, 99.5 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem: 3750588 total, 2459188 used, 1291400 free, 126660 buffers
KiB Swap: 0 total, 0 used, 0 free, 1361336 cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
12571 kevin 20 0 1167372 98148 31888 S 2.0 2.6 0:07.13 chrome
12575 kevin 20 0 1167372 98148 31888 S 0.0 2.6 0:00.60 Chrome_Chi+
12576 kevin 20 0 1167372 98148 31888 S 0.0 2.6 0:00.00 VC manager
12577 kevin 20 0 1167372 98148 31888 S 0.0 2.6 0:00.00 HTMLParser+
12578 kevin 20 0 1167372 98148 31888 S 0.0 2.6 0:00.00 Media
12591 kevin 20 0 1167372 98148 31888 S 0.0 2.6 0:00.00 FFmpegDemu+
12593 kevin 20 0 1167372 98148 31888 S 0.0 2.6 0:00.02 AudioOutpu+
它會列出此進程下所有的線程數,線程數即爲TID,裏面標注出了每個線程佔用CPU的資源數和佔用的時間,根據此結果我們發現這兩個線程是有問題的;
接下來我們要根據線程找到實際在CPU中運行的程序堆棧;
3.有了線程ID:10001,10002,我們需要首先將其轉換爲十六進制:
printf "%x\n" 10001
輸出:2711
printf "%x\n" 10101
輸出:2776
4.1 kill -3 10000 完了去日誌中找到輸出的信息,然後 拿着線程ID:10001,10101的十六進制去日誌中定位;
4.2 對於java程序還可以使用它的debug工具:jstack 10000|grep 2711 -A 30打印出包含此地址的線程堆棧,從而找到Java程序中哪些代碼一直在CPU中佔着資源不釋放;
打印出的堆棧信息如:
见附件图