內(nèi)存分析工具M(jìn)AT(Memory Analyzer Tool)的安裝與使用

一、安裝
1.1、在Eclipse上安裝MAT插件,步驟如下:
點(diǎn)擊Help,Install New Soft,就出現(xiàn)了以下Install界面:然后我們點(diǎn)擊ADD,在彈出的框中填上Mat插件的地址:http://download.eclipse.org/mat/1.6/update-site/,確定后,
點(diǎn)擊Select All,點(diǎn)擊Next,之后就一直確定,就能安裝了。安裝之后需要重啟Eclipse.

image.png

1.2、安裝獨(dú)立版本的MAT
把下載好的壓縮包解壓到本地任意一個(gè)文件夾里,和eclipse一樣,解壓完成就可以使用了。下圖是我的解壓路徑。解壓完成點(diǎn)擊箭頭指向的執(zhí)行文件啟動MAT程序。
下載地址:http://www.eclipse.org/mat/downloads.php
image.png

二、使用
2.1、實(shí)例: 我啟動一個(gè)web容器,在其中配置一個(gè)selvelt,selvelt啟動時(shí)會執(zhí)行一條問題程序,導(dǎo)致堆內(nèi)存溢出,代碼如下

public class myselvelt extends HttpServlet {
    private String[] strings = new String[1000];
    public void init(ServletConfig config) {
        System.out.println("-----------------------------");
        Timer timer = new Timer();
        timer.schedule(new mytime(), 10000);        
    }
    
    class mytime extends TimerTask{
        @Override
        public void run() {
            System.out.println("-------------mytime----------------");
            Map<String,Object> m = new HashMap<String,Object>();
            int i = 0;
            do{
                OutOfMemoryTest test = new OutOfMemoryTest();
                m.put(String.valueOf(i), test);
                i++;
            }while(i<100000);
        }
    }
    
    protected void doGet(HttpServletRequest req,HttpServletResponse resp) throws ServletException,java.io.IOException
    {
        resp.getWriter().println("I am httpServlet doGet()");
    }
 
    protected void doPost(HttpServletRequest req,HttpServletResponse resp) throws ServletException,java.io.IOException
    {
        resp.getWriter().println("I am httpServlet doPost()");
    }
    public void destory(ServletConfig config){
        
    }
}

然后設(shè)置容器運(yùn)行參數(shù):-Xms128m -Xmx256m -XX:MaxPermSize=256m

啟動程序,直到堆內(nèi)存溢出


image.png

2.2、導(dǎo)入dump的文件


image.png

image.png

image.png

image.png

2.3、分析問題
首先由此餅狀圖就可以看出問題出現(xiàn)a、b上,再看兩問題的簡單描述,b是出現(xiàn)在org.apache.catalina.loader.WebappClassLoader 中的,此是容器涉及的區(qū)域,可以排除,再看a描述為一個(gè)Timer-5的線程占據(jù)的51%的堆空間,所以基本可以斷定問題出現(xiàn)在a上(這里還有一個(gè)比較直觀,但不高效的辦法,就是重新設(shè)置一下運(yùn)行容器的參數(shù),運(yùn)行直到出錯,再導(dǎo)入dump的文件,就可以對比餅狀圖,百分百變化很明顯的就是問題原因出現(xiàn)的位置)


image.png

image.png

再查看問題a的詳情
先看到累積點(diǎn)的最短路徑


image.png

可以看到線程:地址是0xf7efbc18 ,名稱為Timer-5,其中累積的為一個(gè)[java.util.HashMap]
然后再看累積對象所在樹的詳情
image.png

可以看到積累了很多HashMap

然后切換一個(gè)視圖查看


image.png

image.png

在第一行輸入問題線程名(Timer-5)進(jìn)行查詢,進(jìn)入找到累積點(diǎn)(堆占據(jù)最大)
image.png

image.png

可以看到累積了22364個(gè)hashMap<String,OutOfMemoryTest>對象,這就是問題的根源

然后再跟蹤堆棧找到問題代碼所在位置


image.png

此處比較簡單,就是一個(gè)Timer-->myselvelt-->OutOfMemoryTest-->OutOfMemoryError
可以看到問題可能是myselvelt.java的34行,OutOfMemoryTest.java的7行
找到對應(yīng)的代碼區(qū)查找


image.png

image.png

這里基本就可以會轉(zhuǎn)到文章開始了,也就是問題實(shí)例,是myselvelt中的問題所在點(diǎn)(myselvelt.java的34行)

三、獲取內(nèi)存dump文件
3.1、通過jdk自帶的jmap命令獲取 jmap -dump:format=b,file=D:\dump\dumpName.hprof [pid]


image.png

3.2、在jdk啟動加參數(shù)中加: -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:\dump\ ,然后應(yīng)用啟動后出現(xiàn)內(nèi)存異常則會自動導(dǎo)出dump文件,默認(rèn)的文件名是:java_pid<進(jìn)程號>.hprof。

注意:獲取dump文件必須是一出現(xiàn)內(nèi)存異常就獲取dump文件,這樣獲取的文件信息才比較準(zhǔn)確,如果過了一段時(shí)間在導(dǎo)出dump文件,就會因gc的緣故,導(dǎo)致信息不準(zhǔn)確,所以推薦第二種方式獲取dump文件。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容