Java應用CPU過高的排查全流程
引言
Java CPU 飆高90% 都是業(yè)務代碼死循環(huán)、頻繁GC、密集計算、死鎖/自旋導致的,排查有標準、固定、可落地的流程,不需要猜。
下面給你一套從登錄服務器到定位代碼行的完整實戰(zhàn)步驟,直接照著做就能定位問題。
一、快速定位:哪個進程占用 CPU 最高
1. 查看系統(tǒng)整體 CPU 占用
top
找到 CPU 使用率最高的 Java 進程 PID(第一列)。
二、精準定位:這個進程里哪個線程在耗 CPU
2. 查看該 Java 進程內(nèi)的線程排行
top -H -p <PID>
會列出該 Java 進程內(nèi)部所有線程,找到CPU 最高的線程 TID。
3. 把線程 TID 轉(zhuǎn)成 16 進制(JVM 棧用 16 進制標識線程)
printf "%x\n" <TID>
得到一個16 進制線程 ID(記下來,后面要用)。
三、抓取線程棧:找到耗 CPU 的代碼
4. 導出 Java 線程棧
jstack <PID> > stack.log
5. 在棧文件里搜索剛才的 16 進制線程 ID
grep -A 20 <16進制TID> stack.log
-A 20 表示顯示后 20 行,直接就能看到:
- 線程名稱
- 線程狀態(tài)
- 具體耗 CPU 的代碼類、方法、行號
四、最常見的 4 種 CPU 飆高原因(一看棧就知道)
1. 死循環(huán) / 無限遞歸(最常見)
棧特征:
com.xxx.service.UserService.getUserList(UserService.java:88)
代碼一直卡在同一行,沒有阻塞,一直在跑。
2. 頻繁 Full GC / Young GC
棧特征:
VM Thread GC task thread
排查命令:
jstat -gc <PID> 1000 10
如果 FGC(FullGC次數(shù))每秒漲好幾次,就是內(nèi)存泄漏/GC 導致 CPU 高。
3. 大量鎖自旋 / CAS 空循環(huán)
棧特征:
sun.misc.Unsafe.park java.util.concurrent.locks
線程處于 RUNNABLE 但一直在自旋。
4. 密集計算(加密、循環(huán)、正則、JSON 解析)
棧會停留在:
- 加密工具類
- 復雜 for 循環(huán)
- 正則表達式(災難性回溯)
- JSON/XML 序列化
五、1 分鐘快速排查腳本(直接復制用)
把下面內(nèi)容保存為 check_cpu.sh,一鍵定位耗 CPU 代碼行:
#!/bin/bash
PID=$1
jstack $PID > stack.log
TID=$(top -b -n 1 -H -p $PID | grep java | sort -nrk 9 | head -1 | awk '{print $1}')
HEX_TID=$(printf "%x\n" $TID)
echo "高耗CPU線程16進制:$HEX_TID"
grep -A 30 $HEX_TID stack.log
使用:
chmod +x check_cpu.sh ./check_cpu.sh <Java進程PID>
六、定位到代碼后怎么解決?
- 死循環(huán):檢查循環(huán)條件、邊界值、迭代邏輯
- 頻繁GC:查內(nèi)存泄漏(用 jmap 堆 dump)、調(diào)整堆大小
- 鎖自旋:改用公平鎖、減少鎖競爭、異步化
- 密集計算:異步執(zhí)行、分片、緩存結(jié)果、優(yōu)化算法
七、必備工具(無需安裝)
Linux + JDK 自帶,生產(chǎn)環(huán)境直接用:
top:看進程/線程 CPUjstack:線程棧jstat:GC 監(jiān)控jmap:堆內(nèi)存 dump(定位內(nèi)存泄漏)
總結(jié)
- top 找 Java 進程 PID
- top -H 找耗 CPU 線程 TID
- 轉(zhuǎn) 16 進制
- jstack + grep 定位代碼行
- 按棧特征判斷是死循環(huán)/GC/鎖/密集計算
整個流程不重啟、不影響業(yè)務、1~3 分鐘定位根因。
到此這篇關(guān)于Java應用CPU過高的排查全流程的文章就介紹到這了,更多相關(guān)Java應用CPU過高排查內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解決引用slf4j中Logger.info只打印出文字沒有數(shù)據(jù)的問題
這篇文章主要介紹了解決引用slf4j中Logger.info只打印出文字沒有數(shù)據(jù)的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12
Java ApiPost請求返回406狀態(tài)碼問題的解決方案
APIPost是一款專為開發(fā)者和測試人員設計的API測試工具,類似于Postman,但提供了更多的團隊協(xié)作和文檔管理功能,它可以幫助你更好地進行接口調(diào)試和集成測試,但遇到了請求后返回的是406狀態(tài),所以本文給大家介紹了Java ApiPost請求返回406狀態(tài)碼問題的解決方案2025-04-04
Java中final關(guān)鍵字的使用與注意總結(jié)
這篇文章主要給大家介紹了關(guān)于Java中final關(guān)鍵字的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者使用Java具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧2020-08-08

