Java程序內存分析:使用mat工具分析內存佔用

    MAT 不是一個萬能工具,它並不能處理全部類型的堆存儲文件。可是比較主流的廠家和格式,例如 Sun, HP, SAP 所採用的 HPROF 二進制堆存儲文件,以及 IBM 的 PHD 堆存儲文件等都能被很好的解析。下面來看看要怎麼作呢,也許對你有用。官方文檔:http://help.eclipse.org/luna/index.jsp?topic=/org.eclipse.mat.ui.help/welcome.htmlphp

形成OutOfMemoryError緣由通常有2種:html

一、內存泄露,對象已經死了,沒法經過垃圾收集器進行自動回收,經過找出泄露的代碼位置和緣由,纔好肯定解決方案;
二、內存溢出,內存中的對象都還必須存活着,這說明Java堆分配空間不足,檢查堆設置大小(-Xmx與-Xms),檢查代碼是否存在對象生命週期太長、持有狀態時間過長的狀況。
java


1. 用jmap生成堆信息

    這樣在E盤的jmap文件夾裏會有一個map.bin的堆信息文件 sql

2. 將堆信息導入到mat中分析   


3. 生成分析報告

    mat能夠爲咱們生成多個報告:apache

        

        


    下面來看看生成的這些數據對咱們有什麼幫助tomcat

    

    從上圖能夠看到它的大部分功能,在餅圖上,你會發現轉儲的大小和數量的類,對象和類加載器。
正確的下面,餅圖給出了一個印象最大的對象轉儲。移動你的鼠標一片看到對象中的對象的細節檢查在左邊。下面的Action標籤中:
服務器

    • Histogram能夠列出內存中的對象,對象的個數以及大小。架構

    • Dominator Tree能夠列出那個線程,以及線程下面的那些對象佔用的空間。app

    • Top consumers經過圖形列出最大的object。eclipse

    • Leak Suspects經過MA自動分析泄漏的緣由。

    Histogram

        

    • Class Name : 類名稱,java類名

    • Objects : 類的對象的數量,這個對象被建立了多少個

    • Shallow Heap :一個對象內存的消耗大小,不包含對其餘對象的引用

    • Retained Heap :是shallow Heap的總和,也就是該對象被GC以後所能回收到內存的總和


    通常來講,Shallow Heap堆中的對象是的大小和保留內存大小相同的對象是堆內存的數量時,將釋放對象被垃圾收集。
    保留設置一組主要的對象,例如一個特定類的全部對象,或全部對象的一個特定的類裝入器裝入的類或者只是一羣任意對象,是釋放的組對象若是全部對象的主要設置變得難以接近的。保留設置包括這些對象以及全部其餘對象只能經過這些對象。保留大小是總堆大小中包含的全部對象的保留。摘自eclipse


    關於的詳細講解,建議你們查看Shallow heap & Retained heap,這是個很重要的概念。

    這兒藉助工具提供的regex正則搜索一下咱們本身的類,排序後看看哪些相對是佔用比較大的。

    左邊能夠看到類的詳細使用,好比所屬包,父類是誰,所屬的類加載器,內存地址,佔用大小和回收狀況等

    這兒有個工具能夠根據本身的需求分組查找,默認根據class分組,相似咱們sql裏的group by了~~

    這裏能夠看到上面3個選項,分別生成overview、leak suspects、top components數據,可是這兒生成的不是圖表,若是要看圖表在(Overview)中的Action標籤裏點擊查看。

    這個是Overview中的 Heap Dump Overview視圖,從工具欄中點開,這是一個全局的內存佔用信息

    Used heap dump 79.7 MB
    Number of objects 1,535,626
    Number of classes 8,459
    Number of class loaders 74
    Number of GC roots 2,722
    Format hprof
    JVM version
    Time 格林尼治標準時間+0800上午9時20分37秒
    Date 2014-7-2
    Identifier size 32-bit
    File path E:\jmap\map.bin
    File length 108,102,005
    • Total: 12 entries


    而後能夠點開SystemProperties和Thread Overview進行查看,我這裏就不貼了內容比較多。

    Dominator Tree

    咱們能夠看到ibatis佔了較多內存

    Top consumers

    這張圖展現的是佔用內存比較多的對象的分佈,下面是具體的一些類和佔用。

    按等級分佈的類使用狀況,其實也就是按使用次數查看,java.lang.Class被排在第一

    還有一張圖是咱們比較關心的,那就是按包名看佔用,根據包咱們知道哪些公共用的到jar或本身的包占用

    這樣就能夠看到包和包中哪些類的佔用比較高。

    Leak Suspects

    這份報告,看到該圖深色區域被懷疑有內存泄漏,能夠發現整個heap只有79.7M內存,深色區域就佔了62%。因此,MAT經過簡單的報告就說明了項目是有可疑代碼的,具體點開詳情來找到類

    點擊鼠標,在List Objects-> with outgoing references下能夠查看該類都引用了什麼對象,由此查看是否由於其餘對象致使的內存問題。

    下面繼續查看pool的gc ROOT

    以下圖所示的上下文菜單中選擇 Path To GC Roots -> exclude weak references, 過濾掉弱引用,由於在這裏弱引用不是引發問題的關鍵。

    進入查看便可,我這兒的代碼沒有問題,就不用貼了。


    The classloader/component "org.apache.catalina.loader.WebappClassLoader @ 0xa34cde8" occupies 19,052,864 (22.80%) bytes. The memory is accumulated in one instance of "java.util.HashMap$Entry[]" loaded by "<system class loader>".

    Keywords
    java.util.HashMap$Entry[]
    org.apache.catalina.loader.WebappClassLoader @ 0xa34cde8


    這段話是在工具中提示的,他告訴咱們WebappClassLoader佔了19,052,864 字節的容量,這是tomcat的類加載器,JDK自帶的系統類加載器中佔用比較多的是HashMap。這個其實比較正常,你們常常用map做爲存儲容器。

    除了在上一頁看到的描述外,還有Shortest Paths To the Accumulation Point和Accumulated Objects部分,這裏說明了從GC root到匯集點的最短路徑,以及完整的reference chain。觀察Accumulated Objects部分,java.util.HashMap的retained heap(size)最大,因此明顯類實例都彙集在HashMap中了。

    來看看Accumulated Objects by Class區域,這裏能找到被彙集的對象實例的類名。java.util.HashMap類上頭條了,被實例化了5573次,從這兒看出這個程序不存在什麼問題,由於這個數字是比較正常的,可是當出問題的時候咱們都會看到比較大的自定義類會在前面,並且佔用是至關高。

    固然,mat這個工具還有不少的用法,這裏把我瞭解的分享給你們,無論如何,最終咱們須要得出系統的內存佔用,而後對其進行代碼或架構,服務器的優化措施!

參考文獻:

http://www.eclipse.org/mat/about/screenshots.php

http://www.ibm.com/developerworks/cn/opensource/os-cn-ecl-ma/

相關文章
相關標籤/搜索