要定位問題,首先你需要獲取服務器jvm某刻內存快照。jdk自帶的jmap可以獲取內存某一時刻的快照,導出為dmp文件后,就可以用Eclipse MAT來分析了,找出是那個對象使用內存過多.
1. top 一下獲取內存占用率最高的pid。
2. 轉到 jdk的bin目錄,執行jdk命令。
一. jstat
(1)./jstat -gc pid 查看gc的次數,及時間。最后五項,分別是young gc的次數,young gc的時間,full gc的次數,full gc的時間,gc的總時間。
jstat -gc pid [interval] 命令查看了 Java 進程的 GC 狀態,果然,FULL GC 達到了每秒一次

這么多的 FULL GC,應該是內存泄漏沒跑了,於是使用 jstack pid > jstack.log 保存了線程棧的現場。
使用 jmap -dump:format=b,file=heap.log pid 保存了堆現場,然后重啟了探測服務,報警郵件終於停止了。
(2)./jstat -gcutil pid 統計gc信息統計
二. jmap
(1)./jmap -heap pid 查看JVM空間總體使用情況
(2)./jmap -histo pid |more 查看類的實例數和內存量
(3)./jmap -histo:live pid |more 查看所有活着的實例數量。
(4)./jmap -dump:format=b,file=dump_tomcat.dat pid 將內存使用情況dump到文件中
3. 使用MAT工具對dump文件進行分析。
下載MAT(Memory Analyzer Tool),一個基於Eclipse的內存分析工具,是一個快速、功能豐
富的JAVA heap分析工具,它可以幫助我們查找內存泄漏和減少內存消耗。
下載地址:http://www.eclipse.org/mat/downloads.php
然后解壓,跟eclipse一樣,我們直接啟動就可以了,啟動界面如下,我們點擊左上角“file”或者紅框中的“Open a Heap Dump”就可以打開我們的Dump文件。

Dump文件后綴問題,找不到Dump文件時選擇All file,就可以看到了

2. 選擇Leak Suspects Report(泄露嫌疑報告),進入到主界面

3. 看到主界面,Problem區域就是提示可能有問題的類的信息了,我們可以看到,有一個類的實例占了700M左右,占用了內存總量90%以上了,點擊Details可以查看詳情,點擊See stacktrace可以查看跟蹤堆棧找到問題代碼所在位置。

其中深藍色的部分就為內存泄漏的部分,java的堆內存一共只有717.8 M而內存泄漏的部分獨自占有了72.8 M所以本次的內存泄漏很明顯。
4. 下圖可以看出來這個對象占用了很多的內存


當然我們也可以切換視圖,查看具體對象的一些信息,可以看到這個class生成了133w個實例,肯定是代碼出問題了

跟蹤代碼,定位泄露位置
點擊See stacktrace,下圖是跟蹤的代碼位置,可以清晰的看到是第幾行生成的對象,進而分析代碼

