記一次MAT內存分析

1、背景

記錄一次內存分析的簡單實踐,目的是找出佔用內存較大的對象和無效的內存分配

2、工具

2.1、 DDMS或者Android Studio

DDMS:抓取內存快照

Android Studio的Profiler:抓取內存快照並分析(支持android 5.0以上)

2.2、 MAT(Memory Analyzer)

內存快照文件分析工具

3、步驟

3.1、 抓取內存快照

DDMS支持5.0以下的系統,以DDMS爲例。

在這裏插入圖片描述
在這裏插入圖片描述

選擇目標apk,並抓取內存快照,可以先GC幾次確保內存快照準確。

生成hprof文件並轉換。這時生成的文件不能直接使用,要經過轉換。轉換工具在Android SDK的platform-tools目錄下,如:

xxx\Android\SDK\platform-tools\hprof-conv.exe -z xxx\xxx\src.hprof xxx\xxx\src-conv.hprof

生成的src-conv.hprof文件就可以在mat中打開了。

3.2 分析內存快照

3.2.1、總覽

打開上一步得到的hprof文件
在這裏插入圖片描述

這裏可以看到大致的內存佔用信息,放到餅狀圖上,還能看到具體的佔用對象,如:
在這裏插入圖片描述
在這裏插入圖片描述
這裏看到佔用最多的是bitmap,其次是glide。

3.2.2、Dominator Tree

直觀地列出大對象

在這裏插入圖片描述

3.2.3、Histogram統計

Histogram可以統計出各個對象佔用的具體大小,並可以排序、篩選等。比如這裏按Retained Heap降序排

在這裏插入圖片描述

能看到具體是什麼對象,佔用了多少內存,對象有多少個等信息。

3.2.4 with outgoing/incoming references

列出引用對象

  • with outgoing references:我引用了誰
  • with incoming references:誰引用了我

這裏bitmap佔用最大,選中bitmap右鍵:

在這裏插入圖片描述

比如查看什麼對象引用了bitmap(with incoming references):

在這裏插入圖片描述

可以看到有兩個對象引用了bitmap,分別是IndexLoadingDialog裏的mIvLoading和TextSeekBar裏的mProgressDrawable。

3.2.5 Merge Shortest Paths to GC Roots

如果上面的方法還不夠直接的話,可以使用Merge Shortest Paths to GC Roots

在這裏插入圖片描述

可以篩選引用類型:如去除弱引用、軟引用等,這裏選只保留強應用,即exclude all phantom/weak/soft etc. references

在這裏插入圖片描述

這裏很直觀的顯示了引用對象。

3.2.6 利用表達式篩選

在Histogram統計界面,可以利用正則表達式篩選出想看的類,比如使用包名篩選:

在這裏插入圖片描述
針對性的去查找大內存對象。

3.3 優化大內存對象

通過上面的分析,已經大致知道了什麼對象佔用內存比較大和引用位置。就可以針對具體的對象進行優化了,比如這裏圖片壓縮一下、TextSeekBar只用於下載更新apk時使用,可以用ViewStub標籤延遲加載等。假設IndexLoadingDialog裏的mIvLoading可以去掉,去掉之後重複上面的步驟:

在這裏插入圖片描述

可以看到內存已經從之前的4.2m降到了345k。

4、結語

mat還可以分析內存泄漏,比如打開/關閉activity多操作幾次,查看內存快照中activity的對象個數,就可以判斷是否存在泄漏了。雖然看了不少內存優化的文章、介紹,但是一直都沒有什麼實感,這次終於有了把理論用到了實踐當中的感覺。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章