天天看點

面試被問到如何排查JVM問題的,如何回答?

作者:備戰面試

一、首先說可用工具

1、jmap可以檢視目前Java程序的記憶體占用,把記憶體快照dump出來

用法:jmap [option] <pid>

常用指令

jmap -heap pid

主要顯示堆的記憶體使用情況,包括分代情況,每個代的總容量、已使用記憶體、可使用記憶體,如圖:

面試被問到如何排查JVM問題的,如何回答?

jmap樣例

jmap -dump:live,format=b,file=xxx.xxx [pid]

目前Java程序的記憶體占用情況導出來,用記憶體分析工具分析,如MAT

2、jstack可以檢視線程運作情況,是否有死鎖,cpu過高問題

用法:jstack [option] <pid>

常用指令

jstack -l pid 生成虛拟機目前時刻的線程快照

需要關注的狀态:deadlock:死鎖,blocked:線程被阻塞,

通過top指令定位到cpu占用率較高的線程之後,接着使用jstack pid指令來檢視目前java程序的堆棧狀态,将線程id轉換成16進制來檢視,建議隔段時間再執行一次stack指令,再一次擷取thread dump,畢竟兩次拍片結果(jstack)對比

3、jstat指令來檢視垃圾回收的情況,特别是fullgc

常用指令:

jstat -gc <pid>

面試被問到如何排查JVM問題的,如何回答?

jstat樣例

參數介紹:

S0C:年輕代中第一個survivor(幸存區)的容量 (位元組)

S1C:年輕代中第二個survivor(幸存區)的容量 (位元組)

S0U:年輕代中第一個survivor(幸存區)目前已使用空間 (位元組)

S1U:年輕代中第二個survivor(幸存區)目前已使用空間 (位元組)

EC:年輕代中Eden(伊甸園)的容量 (位元組)

EU:年輕代中Eden(伊甸園)目前已使用空間 (位元組)

OC:Old代的容量 (位元組)

OU:Old代目前已使用空間 (位元組)

MC:metaspace(元空間)的容量 (位元組)

MU:metaspace(元空間)目前已使用空間 (位元組)

CCSC:目前壓縮類空間的容量 (位元組)

CCSU:目前壓縮類空間目前已使用空間 (位元組)

YGC:從應用程式啟動到采樣時年輕代中gc次數

YGCT:從應用程式啟動到采樣時年輕代中gc所用時間(s)

FGC:從應用程式啟動到采樣時old代(全gc)gc次數

FGCT:從應用程式啟動到采樣時old代(全gc)gc所用時間(s)

GCT:從應用程式啟動到采樣時gc用的總時間(s)

jstat -gc <pid> <n> n 間隔n毫秒列印,可以動态觀察

面試被問到如何排查JVM問題的,如何回答?

二、再說分析思路

1、如果CPU過高

使用top -Hp <pid>,jstack <pid》,十六進制轉換等一頓操作,找到占cpu高的線程,根據堆棧資訊可以找到占用CPU最多的線程,定位到具體的方法,分析原因,比如自旋鎖、遞歸等;

另外更多情況是,占用CPU最多的線程是GC線程,這就說明記憶體使用不當,瘋狂fullgc,j将CPU占滿,這時候需要分析記憶體占用。

2、頻繁fullgc

如果頻繁發生fullgc但是又一直沒有出現記憶體溢出,那麼表示fullgc實際上是回收了很多對象了,是以這些對象最好能在younggc過程中就直接回收掉,避免這些對象進入到老年代,對于這種情況,就要考慮這些存活時間不長的對象是不是比較大,導緻年輕代放不下,直接進入到了老年代,嘗試加大年輕代的大小,如果改完之後,fullgc減少,則證明修改有效。

3、如果已經發生oom

一般生産系統中都會設定當系統發生了OOM時,生成當時的dump檔案(-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/usr/local/base),如果沒設定,需要設定重新開機,嘗試複現問題。我們可以利用jvisualvm、MAT等工具來分析dump檔案,根據dump檔案找到異常的執行個體對象,和異常的線程(占用CPU高),定位到具體的代碼,然後再進行詳細的分析和調試。

三、最後總結

總之,調優不是一蹴而就的,需要分析、推理、實踐、總結、再分析,最終定位到具體的問題。

還希望補充什麼内容,大家在評論區留言,一起探讨!

點選關注,期待後續精彩内容!