Java的記憶體泄露多半是因為對象被遺留在全域的HashMap中得不到釋放,如果發現Java應用程式佔用的記憶體出現了泄露的跡象,那麼我們一般採用下面的步驟分析:
1. 把Java應用程式使用的heap dump下來
2. 使用Java heap分析工具(如MAT),找出記憶體佔用超出預期的嫌疑對象
3. 根據情況,分析嫌疑對象和其他對象的參考關聯性。
4. 剖析器的原始碼,找出嫌疑對象數量過多的原因。
產生heap dump檔案的方法:
方法一:使用jdk的jmap命令,在運行中的JVM產生Dump檔案
jmap -dump:format=b,file=/path/heap.bin 進程ID
如果只dump heap中的存活對象,則加上選項-live,如下:
jmap -dump:live,format=b,file=/path/heap.bin
進程ID
方法二:讓JVM在遇到OutOfMemoryError時產生Dump檔案
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path
用MAT(Memory Analyzer)分析dump檔案:
在eclipse中安裝MAT外掛程式(http://www.eclipse.org/mat/),然後在eclipse中,file---->open,開啟這個檔案heap.bin,如:
從可以看到它提供的一些功能:
1) Histogram可以查看記憶體中的對象,對象的個數以及大小。
2.)Dominator Tree可以列出線程,以及線程下面的那些對象佔用的空間。
3)Top consumers通過圖形列出最大的object。
4)Leak Suspects通過MA自動分析泄漏的原因。
點擊Histogram連結,如下:
(註:在一個正常業務系統中,char[] 佔用70-90%的是非常正常的。)
中,共有4列:
Class Name:列出的是類名
Objects:類的對象的數量
Shallow Heap:對象本身佔用記憶體的大小,不包含對其他對象的引用,也就是對象頭加成員變數(不是成員變數的值)的總和
Retained Heap:是該對象自己的shallow size,加上從該對象能直接或間接訪問到對象的shallow size之和。換句話說,retained size是該對象被GC之後所能回收到記憶體的總和。