1. 程式人生 > >內存泄露排查記錄

內存泄露排查記錄

from stat 占用 tro chain 三方 ots ins size

一 、問題定位

手段一:通過 jstat -gcutil 快速定位GC問題(首先)

命令格式: jstat -gcutil <pid> <period>

命令樣例:jstat -gcutil 11900 3s

------> 監控進程11900的GC情況, 每3s輸出一條記錄。

要點:O列(老年代內存使用率)一直接近100%;

   FG列(Full GC次數) 一直增長。

手段二:增加Xmx參數,加大堆內存排除堆內存過小因素影響。

在jstat -gcutil 的O列占滿情況,需進一步排除是否是堆內存分配過小,滿足不了業務請求量導致。

查看最大堆內存命令:jinfo -flag MaxHeapSize <pid> 。

假如開始是4G,修改成8G:java -Xmx8G

要點:增加最大堆內存後,使用jstat -gcutil 看O列是否滿負,如果還是滿負, 則可基本確定是內存泄露。

手段三:使用 jmap -histo 命令定位內存泄露具體對象。

該命令展示所有類的實例個數以及內存用量情況,並按照使用量降序輸出,一般自己寫的類有內存泄露,那會名列前茅。

命令1:jmap -histo <pid>

命令樣例:jmap -histo 42530 | head -n 20

輸出對應進程當前所有存活對象的堆內存占用情況,找到"突出" 的嫌疑類。

命令2:jmap -histo:live <pid>

帶上live,會觸發一次Full GC後再輸出結果,實際上就是回收了無用的對象,輸出真正存活的對象情況。如果嫌疑類名實例數不減,那麽十有八九這個類就是導致內存泄露根因。

要點:兩個命令對比觀察Full GC後,實例數不減的類,重點關註排在前面的幾個自己寫的類名。

手段四:使用 jmap -dump:file 導出堆內存數據。

通過手段三,一般可以定位出代碼位置,但代碼中很多地方引用了這個類,則要導出 Dump 文件,進一步分析泄露對象的GCRoot 。

命令:jmap -dump:file=<文件名> <pid>

樣例:jmap -dump:file=app.dump 9336

分析dump文件的工具:除了JDK自帶的 jhat , jvisualvm ,還有第三方的MAT,jprofiler等。

內存泄露的話,dump文件也會很大,為了防止卡死,一般會將Xmx控制在一個合適的大小(2G) ,重現問題後, 再導出dump 。

要點:將Xmx設小一點,再導出dump。

手段五:jhat分析dump文件,尋找GC Root。

因為網絡拷貝大容量的dump文件諸多不便,所以需要現網直接分析dump文件,jhat可以啟動一個http服務,提供頁面遠程分析對象引用情況。

命令:jhat -J-Xmx2G -port <port> <dump文件>

樣例:jhat -J-Xmx2G app.dump

其中Xmx2G代表使用2G堆內存運行jhat,下一步可瀏覽器分析了,URL:http://ip:7000

要點:首先鏈接到嫌疑類的具體某個對象頁面,分析這個對象的引用情況是否正常,再通過“Reference chains from Rootset ”獲取所有的GC Root ,進而定位到具體代碼位置。

內存泄露排查記錄