性能優(yōu)化工具(八)-MAT

一、簡介

MAT是Memory Analyzer tool的縮寫,是一種快速,功能豐富的Java堆分析工具,能幫助你查找內存泄漏和減少內存消耗。很多情況下,我們需要處理測試提供的hprof文件,分析內存相關問題,那么MAT也絕對是不二之選。 Eclipse可以下載插件結合使用,也可以作為一個獨立分析工具使用,下載地址:MAT

二、獲取hprof文件

我們先了解如何獲取hprof文件
在AS monitor 的 memory部分,進行如下操作:

左邊欄選擇Captures,在Heap Snapshot文件夾內會生成對應的hprof文件,再轉化為可供MAT使用的標準hprof文件,操作如下:

如果不用MAT,那么不需要轉為標準hprof文件,在右邊部門就能看到分析報表,可以進行對應分析。但是建議還是使用MAT工具分析,功能更加全面些。

三、MAT工具使用介紹

如何下載和安裝這里就不講了,自行百度或者google。

用工具打開標準.hprof文件后界面如下:

我們主要分析Actions, 它包含了4個部分:

視圖 含義
histogram 列舉內存中對象存在的個數(shù)和大小
Dominator tree 該視圖會以占用總內存的百分比來列舉所有實例對象,注意這個地方是對象而不是類了,這個視圖是用來發(fā)現(xiàn)大內存對象的
Top Consumers 該視圖會顯示可能的內存泄漏點
Duplicate Classes 該視圖顯示重復的類等信息

點擊他們能得到不同的視圖,下面來一一介紹:
3.1 Histogram:

點擊Histogram之后,會出現(xiàn)如下界面:


這個視圖中提供了多種方式來對對象進行分類,這里為了分析方便,我們選擇按包名進行分類。

下面再來解釋下列名:

列名 含義
Object 該類在內存當中的對象個數(shù)
Shallow Heap 對象自身所占用的內存大小,不包括它所引用的對象的內存大小
Retained Heap 該對象被垃圾回收器回收之后,會釋放的內存大小

我們再來看一下右鍵菜單選項:

1)List objects:


with outgoing references: 查看它所引用的對象
with incoming references: 查看它被哪些對象引用

2)Show objects by class
和List objects選項類似,只不過列出的是類名。

3)Merge Shortest Paths to GC Roots
我們可以選擇排除一些類型的引用:

3.2 Dominator Tree:

通過“引用樹”的方式來展現(xiàn)內存的使用情況的,通俗點來說,它是站在對象的角度來觀察內存的使用情況的,主要看是否存在異常的大內存對象

3.3 Top consumersDuplicate Classes: 不常用,讀者可以自行使用下

四、簡單案例分析

案例:將Activity的實例被一個單例對象所持有,在旋轉屏幕的時候造成內存泄漏

public class CommonUtils {
    private static CommonUtils instance;
    private Context context;
    private CommonUtils(Context context){
        this.context = context;
    }

    public static CommonUtils getInstance(Context context){
        if(instance == null){
            instance = new CommonUtils(context);
        }
        return instance;
    }
}
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        CommonUtils.getInstance(this);//單例模式內存泄漏
    }
}

4.1生成hprof文件并導入MAT

生成過程不贅述了,2份hprof文件 一份是沒有旋轉過屏幕的, 一份是旋轉過屏幕多次的,用來做泄漏和無泄漏的對比,幫助定位問題。

打開MAT 導入我們的2個hprof文件 Open File-->選擇文件-->Leak Suspects Report-->Finish

4.2生成比較結果表

兩個文件都分別先點擊Action中histogram視圖,然后打開下面的面板Navigation History ,會發(fā)現(xiàn)有兩個histogram,分別選中histogram右鍵add to Compare Basket 添加到比較容器中。

添加到比較容器,然后進行比較:

比較之后生成Compared Tables:

然后通過合理的懷疑和猜測,且通過對比,找出有問題的類。當然,這個列子很簡單,而且位置也很清楚,但是較為復雜的項目,這一步就是體力活了。只能耐著性子一點點分析比較。

定位到hasMemLeak.hprof存在內存泄漏:

下一步,找到hasMemLeak.hprof對應的histogram, 再去觀察MainActivtiy具體被哪些對象引用:

看到MainActivty被引用的地方這么多 而且一屏還顯示不完 我們又如何去判斷是哪個導致內存泄漏的呢 MAT還有一個功能 就是通過遍歷GC Root樹去將那些有可能被GC回收的實例 將他們去除(備注:在GC Root樹中能找到的對象絕對不存在有內存泄漏的實例 因為他們在運行時會被回收的嘛 只有找不到的那些才是:

排除虛引用、弱引用、軟引用,之后剩余的才是有分析價值的:

找到問題然后去修改代碼:

CommUtil instance = CommUtil.getInstance(getApplicationContext());

之后再抓hprof測試修改

分析總結:
通過操作,觀察android monitor的內存變化,在橫豎屏切換或者頁面進入退出之后,內存在短時間沒有明顯回落的,都是內存泄漏的懷疑點。確認幾個合理的懷疑范圍之后,通過抓取對比的hprof文件,先定位到泄漏的類,然后再通過分析它引用了誰或者誰引用了它來定位最終問題。同時可以通過排除虛引用、弱引用、軟引用等等GC可以回收的引用來縮小分析范圍。

不得不承認,MAT分析內存問題,還是比較麻煩的,如果想圖方便的話,下期會講一個傻瓜式工具:LeakCanary.

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
禁止轉載,如需轉載請通過簡信或評論聯(lián)系作者。

友情鏈接更多精彩內容