一、jmap的使用以及內存溢出分析
前面通過jstat可以對jvm堆的內存進行統計分析,而jmap可以獲取到更加詳細的內容,如:內存使用情況的匯總、對內存溢出的定位與分析
1、查看內存使用情況
jmap -heap 29720
2、查看內存中對象數量及大小
#查看所有對象,包括活躍以及非活躍的 jmap ‐histo <pid> | more
#查看活躍對象 jmap ‐histo:live <pid> | more
#查看活躍對象
jmap -histo:live 29720 | more

對象說明:
B byte
C char
D double
F float
I int
J long
Z boolean
[ 數組,如[I表示int[]
[L+類名 其他對象
3、將內存使用情況dump到文件中
有些時候我們需要將jvm當前內存中的情況dump到文件中,然后對它進行分析,jmap也是支持dump到文件中的。
#用法: jmap -dump:format=b,file=dumpFileName <pid>
jmap -dump:format=b,file=../tmp/dump.dat 29720

4、通過jhat對dump文件進行分析
我們將jvm的內存dump到文件中,這個文件是一個二進制的文件,不方便查看,這時我們可以借助於jhat工具進行查看。
#用法: jhat -port <port> <file>
jhat -port 29729 ../tmp/dump.dat
打開瀏覽器進行訪問:http://localhost:29729/

在最后面有OQL查詢功能:
點擊下面選項:
進入頁面,輸入下面語句查詢字符串大於10000,點擊Execute按鈕,查詢結果:
select s from java.lang.String s where s.value.length >= 10000
5、通過MAT工具對dump文件進行分析
5.1 MAT工具介紹
MAT(Memory Analyzer Tool),一個基於Eclipse的內存分析工具,是一個快速、功能豐
富的JAVA heap分析工具,它可以幫助我們查找內存泄漏和減少內存消耗。使用內存分析
工具從眾多的對象中進行分析,快速的計算出在內存中對象的占用大小,看看是誰阻止
了垃圾收集器的回收工作,並可以通過報表直觀的查看到可能造成這種結果的對象。
5.2 下載安裝

解壓后得到的文件列表:
5.3 使用
①雙擊啟動 MemoryAnalyzer.exe應用程序
②打開一個dump文件
③操作如圖兩步
④查看Overview
⑤查看Histogram
⑥查看對象以及它的依賴 dominator_tree
⑦查看可能存在內存泄露的分析
二、內存溢出的定位與分析
內存溢出在實際的生產環境中經常會遇到,比如,不斷的將數據寫入到一個集合中,出
現了死循環,讀取超大的文件等等,都可能會造成內存溢出。
如果出現了內存溢出,首先我們需要定位到發生內存溢出的環節,並且進行分析,是正
常還是非正常情況,如果是正常的需求,就應該考慮加大內存的設置,如果是非正常需
求,那么就要對代碼進行修改,修復這個bug。
首先,我們得先學會如何定位問題,然后再進行分析。如何定位問題呢,我們需要借助
於jmap與MAT工具進行定位分析。
1、模擬內存溢出
編寫代碼,向List集合中添加100萬個字符串,每個字符串由1000個UUID組成。如果程序能夠正常執行,最后打印ok
package com.zn; import java.util.ArrayList; import java.util.List; import java.util.UUID; public class TestJvmOutOfMemory { public static void main(String[] args) { List<Object> list = new ArrayList<>(); for (int i = 0; i < 10000000; i++) { String str = ""; for (int j = 0; j < 1000; j++) { str += UUID.randomUUID().toString(); } list.add(str); } System.out.println("ok"); } }
2、設置VM options參數
-Xms8m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError

3、運行測試
4、當發生內存溢出時,會dump文件到java_pid65828.hprof

5、導入到MAT工具中進行分析

可以看到,有87.99%的內存由Object[]數組占有,所以比較可疑。
分析:這個可疑是正確的,因為已經有超過90%的內存都被它占有,這是非常有可能出
現內存溢出的。
6、查看詳情
可以看到集合中存儲了大量的uuid字符串