Android記憶體最佳化9 記憶體偵查工具3 MAT比Menmery Monitor更強大

來源:互聯網
上載者:User

標籤:軟引用   回收   select   user   har   基本   native   路徑   nal   

在Android效能最佳化第(一)篇---基本概念中講了JAVA的四大引用,講了一下GCRoot,第二篇Memory Monitor檢測記憶體泄露僅僅說了Menmery Monitor的使用,這篇部落格談一下MAT來尋找記憶體泄露,相對來說,Memory Monitor沒有MAT強大,但是在開始介紹MAT之前,上兩篇沒有說清楚的問題先說一下。

  • GC回收對可回收對象的判定
    什麼樣的對象是可以被回收的?
    當然是GC發現通過任何referencechain(引用鏈)無法訪問某個對象的時候,該對象即被回收。名詞GC Roots正是分析這一過程的起點,例如JVM自己確保了對象的可到達性(那麼JVM就是GC Roots),所以GCRoots就是這樣在記憶體中保持對象可到達性的,一旦不可到達,即被回收。通常GC Roots是一個在current thread(當前線程)的call stack(調用棧)上的對象(例如方法參數和局部變數),或者是線程自身或者是system class loader(系統類別載入器)載入的類以及native code(本地代碼)保留的使用中的物件。所以GC Roots是分析對象為何還存活於記憶體中的利器。

GC Root Tracing演算法,對於可回收對象的判定


上面這段話,也寫出了檢測記憶體泄露的基本思想以”GC Roots”的對象作為起始點向下搜尋,搜尋形成的路徑稱為引用鏈,當一個對象到GC Roots沒有任何引用鏈相連(即不可達的),則該對象被判定為可以被回收的對象,反之不能被回收。也寫出了記憶體泄露的原因對象無用了,但仍然可達(未釋放),記憶體回收行程無法回收。

好啦,下面開始介紹MAT,MAT工具全稱為Memory Analyzer Tool,(MAT下載:http://eclipse.org/mat/downloads.php)是一款詳細分析Java堆記憶體的工具,該工具非常強大,為了使用該工具,我們需要hprof檔案。但是該檔案不能直接被MAT使用,需要進行一步轉化,可以使用hprof-conv命令來轉化,但是AndroidStudio可以直接轉化。


匯出標準的hprof檔案


然後用MAT開啟我們匯出的檔案,我匯出了兩個檔案,test1.hprof和test2.hprof,其中test1.hprof是記憶體未泄露時的快照,test2.hprof是記憶體已經泄露的快照。我們用MAT的Histogram(長條圖)和Dominator Tree (支配樹)來分析記憶體情況。Histogram可以列出記憶體中每個對象的名字、數量以及大小。Dominator Tree會將所有記憶體中的對象按大小進行排序,並且我們可以分析對象之間的引用結構。


MAT工具主介面一、 Histogram(長條圖)

可列出每一個類的執行個體數。支援Regex尋找,也可以計算出該類所有對象的retained size。預設是通過class(group by class)分類展示的。


長條圖.png

這就是test2.hprof的長條圖。現在要說兩個名詞解釋。Shallow Heap/Retained Heap

  • Shallow Heap
    Shallow size就是對象本身佔用記憶體的大小,不包含其引用的對象記憶體,實際分析中作用不大。在堆上,看起來是一堆原生的byte[], char[], int[],對象本身的記憶體都很小。所以我們可以看到以Shallow Heap進行排序的Histogram圖中,排在第一位第二位的是byte,char
  • Retained Heap
    Retained size是該對象自己的shallow size,加上從該對象能直接或間接訪問到對象的shallow size之和。換句話說,retained size是該對象被GC之後所能回收到記憶體的總和。RetainedHeap可以更精確的反映一個對象實際佔用的大小(因為如果該對象釋放,retained heap都可以被釋放)。

Histogram中是可以顯示對象的數量的,那麼比如說我們現在懷疑MainActivity中有可能存在記憶體流失,就可以在第一行的Regex框中搜尋“MainActivity”,如下所示:



可以看到MainActivity的數量是2,這不正常,解決這個,就需要查看MainActivity被誰引用了,不能被釋放。我們右鍵選擇exclude all phantom/weak/soft etc.references, 意思是查看排除虛引用/弱引用/軟引用等的引用鏈 (這些引用最終都能夠被GC幹掉,所以排除)



還有其他菜單供選擇

  • List objects with (以Dominator Tree的方式查看)
  • incoming references 引用到該對象的對象
  • outcoming references 被該對象引用的對象
  • Show objects by class (以class的方式查看)
  • incoming references 引用到該對象的對象
  • outcoming references 被該對象引用的對象

當你按上面操作之後,兇手就出現了,原來是UserManger的執行個體。


還有可以通過包名來查看Histogram。


還有更強大的,通過OQL語句查詢,有點像寫SQL語句。



是不是分分鐘查出MainActivity有兩個對象。哈哈!
比如:尋找size=0並且未使用過的ArrayList

select * from java.util.ArrayList where size=0 and modCount=0

這個地方可以多研究研究。

二、Dominator Tree(支配樹)

Dominator Tree是對象之間dominator關係樹。如果從GC Root到達Y的的所有path都經過X,那麼我們稱X dominates Y,或者X是Y的Dominator Dominator Tree由系統中複雜的對象圖計算而來。從MAT的dominator tree中可以看到佔用記憶體最大的對象以及每個對象的dominator。 我們也可以右鍵選擇Immediate Dominator”來查看某個對象的dominator。它可以將所有對象按照Heap大小排序顯示, 這樣大記憶體對象就是排在前幾名的,我們可以搜尋大記憶體對象通向GC Roots的路徑,因為記憶體佔用越高的對象越值得懷疑,使用方法跟Histogram(長條圖)差不多,在這裡我就不做過多的介紹了。

三、記憶體快照對比

我們可以將test1.hprof的長條圖與test2.hprof的長條圖對比來看,其中Object#0是test1.hprof的,Object#1是test2.hprof的,通過比較看哪一些對象的大小相差過大。


記憶體快照對比

其他資料:
官方的協助文檔
http://wiki.eclipse.org/index.php/MemoryAnalyzer

使用 Eclipse Memory Analyzer 進行堆轉儲檔案分析
http://www.vogella.de/articles/EclipseMemoryAnalyser/article.html

MAT使用教程
http://www.vogella.de/articles/EclipseMemoryAnalyser/article.html

Android記憶體最佳化9 記憶體偵查工具3 MAT比Menmery Monitor更強大

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.