Eclipse Memory Analyzer(MAT)使用
平時開發、測試過程中,有時會遇到OutOfMemoryError,Java堆溢出了,這表明程序有嚴重的問題,我們需要找出造成OutOfMemoryError原因。
一般有兩種情況:
1、內存泄露,對象已經死了,無法通過垃圾收集器進行自動回收,通過找出泄露的代碼位置和原因,才好確定解決方案;
2、內存溢出,內存中的對象都還必須存活着,這說明Java堆分配空間不足,檢查堆設置大小(-Xmx與-Xms),檢查代碼是否存在對象生命周期太長、持有狀態時間過長的情況。
以上是處理Java堆問題的思路,具體是怎么進行分析,這里介紹使用Eclipse Memory Analyzer tool(MAT)工具分析的過程。
java.lang.OutOfMemoryError:Java heap space
Java虛擬機堆里面已經沒有更多的空間了。你正准備創建一個新的對象,但是這個要創建的對象需要的內存已經超過了虛擬機所剩的了。虛擬機會嘗試通過full GC來回收內存,如果不行的話,就會拋出這個信息(可以通過-Xmx參數增加堆的大小來解決),如果不行,還是要找到出現問題的原因
java.lang.OutOfMemoryError:PermGen space
和第一個現象差不多,不過這里准備分配內存的空間是持久代。同樣的,空間已經不夠了,(增加了-XX:MaxPermSize這個參數的值,問題通常就解決了)
java.lang.OutOfMemoryError: GC overhead limit exceeded
這個問題有點特殊。這里沒有提示說堆還是持久代有問題,虛擬機只是說程序花在垃圾回收上的時間太多了,卻沒有什么見效。默認的話,如果98%的時間都花在GC上並且回收了才不到2%的空間的話,虛擬機才會拋這個異常。
以上三種錯誤覆蓋了98%以上的場景
java.lang.OutOfMemoryError: unable to create new nativethread
如果虛擬機正在請求操作系統創建一個本地線程,而操作系統無法創建的時候,你會收到這個報錯信息。
java.lang.OutOfMemoryError:nativeGetNewTLA
指當虛擬機不能分配新的線程本地空間(Thread Local Area)的時候錯誤信息。這個異常只有在jRockit虛擬機時才會碰到。線程本地空間是多線程程序里面為了更有效的進行內存分配而建立的緩存。每一個線程都有一份自己的緩存,當這個線程要創建對象的時候,就在這上面分配。如果你有很多線程同時並發,又要創建大量的對象,可能會出現這個問題,這種情況下你可以調整一下-XXtlaSize這個參數
java.lang.OutOfMemoryError:Requested array size exceeds VM limit
當創建一個超過虛擬機允許的大小的數組時,這條錯誤就會出現
java.lang.OutOfMemoryError:request bytes for . Out of swap space
這個錯誤是當虛擬機向本地操作系統申請內存失敗時拋出的。這個和用完了堆或者持久化中的內存的情況有些不同。這個錯誤通常是在程序已經逼近平台限制的時候產生的。這個信息告訴你可能已經用光了物理內存以及虛擬內存了。
二、MAT使用
1、Mat插件安裝
1)下載Mat ,Mat下載地址:http://www.eclipse.org/mat/
2)解壓下載包:放到eclipse或myeclipse安裝目錄的dropins目錄下
3)啟動eclipse或myeclipse,打開window - > open perspective,看到Memory Analysis證明安裝成功
也可以使用其它方法進行安裝,不一一說明
2、生成dump文件
首前制造一條內存泄漏的用例,執行使程序報OutOfMemoryError
# ps -ef | grep java
# jmap -dump:live,format=b,file=mpfile1309

3、使用mat分析
啟動eclipse或myeclipse,打開file - > Open heap dump,在彈出的對話框選擇生成的dump文件(mpfile)打開heapDumps文件,就可以看到MAT給出了overview page

結果查看:
1.Histogram可以列出內存中的對象,對象的個數以及大小。
2. Dominator Tree可以列出那個線程,以及線程下面的那些對象占用的空間。
3.Top consumers通過圖形列出最大的object。
4.Leak Suspects通過MA自動分析泄漏的原因。
分析:
Histogram如下圖:
Objects:類的對象的數量;
Shallow size:就是對象本身占用內存的大小,不包含對其他對象的引用,也就是對象頭加成員變量(不是成員變量的值)的總和;
Retained size:是該對象自己的shallow size,加上從該對象能直接或間接訪問到對象的shallow size之和。換句話說,retained size是該對象被GC之后所能回收到內存的總和。
我們發現cn.test.TestBean類的對象占用了很多空間。

DominatorTree如下圖:

我們發現cn.test.TestMain-java.util.arraylist-java.lang.object用了很多空間
Top consumers如下圖:
這里顯示了內存中最大的對象有哪些,他們對應的類是哪些,類加載器classloader是哪些。
有些時候,我們在這里就可以看到代碼泄露的位置。




Leak Suspects如下圖:
該圖深色區域被懷疑有內存泄漏,深色區域就占了69.1%。后面的描述,告訴我們懷疑問題出在java.lang.object中。所以,MAT通過簡單的報告就說明了問題所在。


通過Leak Suspects的Problem Suspect 1點擊【Details】
從詳細內容中我明可以明確的查出是cn.test.TestBean類的對象有問題,內存溢出


以上是通過MAT分析Tomcat應用程序,找到內存泄露的原因,還有許多不足之處,希望大家多多指教
轉自:https://user.qzone.qq.com/731573705/blog/1436389384