背景
有朋友向我吐槽,她在一臺測驗機器上除錯,使用jmap查看堆記憶體占用時,發現年輕代+老年代占用的記憶體,和dump下堆轉儲檔案使用MAT分析顯示的記憶體不一樣,百思不得其解,重現現象如下:
上圖為jmap顯示的堆使用情況,發現總共占用的記憶體為,Eden的117M+Old的231M=348M,
然而將當前堆記憶體dump下來,使用MAT打開之后,顯示Size為221M?
終究還是不夠細心,難道沒有看到Details展示中的"Unreachable Objects Histogram"?直接到eclipse翻閱檔案,看看什么叫Unreachable Objects(原文在這里),大致意思是說:
有時一個堆dump檔案包含了可能會在下一次GC時被清理掉的物件,站在可達性分析的角度來說,這些物件沒有和GC Roots關聯,MAT認為它們對于分析記憶體問題并不重要,所以默認會在決議dump檔案時將它們洗掉,如果dump檔案是由OOM時自動產生的,那么其中一般不會包含這些物件,因為JVM通常會執行GC以嘗試釋放空間;但是也不一定,比如要新分配的物件太大,JVM無法釋放足夠的空間;或者我們自己手動dump時未使用live引數,
直接點擊"Unreachable Objects Histogram"看一下:

這個結果是一個直方圖,顯示了不可達的物件的類名、物件實體的數量以及它們的總大小,由于不可達的物件在分析dump檔案時被洗掉了,只存盤了類名,所以沒有對應的物件圖表,選定一個class,右鍵"List objects"也無法查看其參考串列,
處理
要想MAT在分析dump時不洗掉Unreachable Objects,修改一下配置即可(當然前提是dump檔案中本就包含這些物件),
1、在Window->Preferences->Memory Analyzer中選中"Keep unreachable objects",然后點擊"Apply and Close"保存配置:
2、關閉已打開的dump檔案,×掉就可以了
3、進入Window->Heap Dump History ,選擇分析的dump檔案,然后右鍵洗掉索引檔案:Delete Index Files,MAT分析dump后會生成很多索引檔案,如果不洗掉這些檔案,MAT就不會重新決議, 可以在這里洗掉,也可以自行到dump檔案所在目錄手動洗掉,
4、然后選擇File,重新打開dump檔案,可以看到Size和預期一致了,不可達的物件沒有被洗掉,然后就可以繼續分析了:
5、選擇Open Query Browser->Java Basics->GC Roots

在gc_roots中選中Unreachable欄位,右鍵選擇"Show Retained Set"


轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/266705.html
標籤:其他
上一篇:武器級工具包 Immunity Canvas 7.26 泄露事件 | 附下載地址
下一篇:【設計模式系列】行為型之策略模式
