內存泄露排查記錄

一 、問題定位java

手段一:經過 jstat  -gcutil  快速定位GC問題(首先)瀏覽器

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

命令樣例:jstat  -gcutil  11900  3sapp

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

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

      FG列(Full GC次數) 一直增加。對象

 

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

在jstat   -gcutil 的O列佔滿狀況,需進一步排除是不是堆內存分配太小,知足不了業務請求量致使。ip

查看最大堆內存命令: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 ,進而定位到具體代碼位置。

相關文章
相關標籤/搜索