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

