天天看點

記憶體洩漏-問題排查

問題現象:請求無響應,線程粘滞。

問題定位:

第一步:通過jstat指令可以檢視JVM的記憶體使用和垃圾回收情況:


jstat –gcutil <pid>  <timediff>  >  <filename>


    <pid>為程序号,<timediff>為每次輸出的間隔ms,> <filename>是将結果輸出至檔案中,可以省略,直接輸出到控制台


該指令的輸出:
           
記憶體洩漏-問題排查
S0、S1:代表S0/S1的記憶體占用百分比


E、O、P:代表Eden、Old、Perm的記憶體占用百分比


YGC、FGC:代表從程序啟動以來YoungGC和FullGC的執行總次數


YGCT、FGCT、GCT:代表從程序啟動以來YoungGC和FullGC的耗時總和,以及整體GC的耗時總和
  觀察Old Gen記憶體占用的增長速度,以及GC的頻次:
           

正常的:

記憶體洩漏-問題排查

異常的:

記憶體洩漏-問題排查

如果jstat指令輸出的記憶體使用與GC資訊是正常的,那麼可以立即排除記憶體洩露的問題,此時應通過線程堆棧資訊繼續嘗試定位原因。

如果jstat指令輸出的資訊表示JVM正在頻繁進行FullGC,那麼基本可以肯定性能故障的原因是記憶體洩露,此時應通過更進一步的手段定位記憶體洩露點
           

第二步:利用記憶體dump分析

記憶體dump包含目前JVM堆和Perm中所有的對象、對象所占的記憶體空間、以及對象間的引用關系等資料,通過分析記憶體dump,能夠明确的找出占用記憶體大的對象,以及可能導緻記憶體洩露的點


指令:jmap –dump:format=b,file= <filename>  <pid>
           

記憶體dump肉眼是不可讀的,需要通過工具分析

解析工具:Eclipse Memory Analyzer(MAT)

使用MAT打開dump檔案,MAT會将dump檔案加載至記憶體中并開始分析(注意,為MAT配置設定的記憶體應大于dump檔案的尺寸,否則分析會因記憶體不足失敗)

MAT解析dump檔案步驟如下:

    加載完成後,MAT會提示要打開哪一種試圖,選擇預設的“Leak Suspect”,即記憶體洩露疑點視圖
           
記憶體洩漏-問題排查

Leak Suspect視圖:

記憶體洩漏-問題排查

點選Details視圖:

記憶體洩漏-問題排查

到目前為止,我們通過分析記憶體dump能夠得出的資訊是:

1個對象,占用了2068的堆記憶體,一個List集合占用了運作記憶體高達1G多記憶體,導緻記憶體洩漏

第三步:利用jstack指令輸出jstack檔案

指令:jstack -l ${PID} > /home/test/jstack/files/ 1. 1. 1.{time}.txt)

記憶體洩漏-問題排查

利用MAT工具分析dump日志後,可以根據線程名稱找到對應jstack檔案日志。以此來推斷那行業務代碼導緻産生記憶體洩漏。