天天看點

App體系化優化之記憶體優化(Memory Analyzer Tool + Memory Profiler)

說明:如果隻是單存的記憶體抖動,AndroidStudio的Memory Profiler就可以分析了,具體分析過程已經有很多文章說明了,這裡就不贅述,接下來要說的是記憶體洩露的追查。

1.MAT下載下傳

MAT 下載下傳位址:https://www.eclipse.org/mat/downloads.php

下載下傳版本:

Mac OSX (Mac/Cocoa/x86_64)

2.MAT安裝和啟動

下載下傳完成,在Downloads目錄下找到

MemoryAnalyzer-1.9.0.20190605-macosx.cocoa.x86_64.zip

解壓檔案,得到

mat.app

目錄。移動到自己的目錄下執行 /xxxxx/mat.app/Contents/MacOS/MemoryAnalyzer -data ./workspace

輸入指令行 : /Users/mac/Desktop/mat/mat.app/Contents/MacOS/MemoryAnalyzer -data ./workspace

App體系化優化之記憶體優化(Memory Analyzer Tool + Memory Profiler)

看到歡迎界面就是成功了。

這是一款用于記憶體分析的工具,主要可以對記憶體洩露(OOM之前)的問題進行分析和定位。配合Memory Profiler分析記憶體洩露導緻的卡頓和線上偶發性的崩潰。

由于我們的app中有一些寫的不合适的代碼片段,導緻記憶體的配置設定非常頻繁,在頻繁的配置設定和GC的情況下就會出現記憶體抖動。當我們使用static不注意的時候就很容易造成 對外部類的強引用,即使不調用不崩潰,但是由于static和app的生命周期相同,是以強引用的對象無法釋放,導緻記憶體無法清理,由于每一個app所配置設定的記憶體是有限的,是以就會導緻記憶體洩露,當洩露到一定程度,剩餘記憶體或者記憶體碎片不足以配置設定的時候就會OOM,崩潰,這就是線上崩潰線下無法複現的問題的來源。

分析步驟:

1.當我們看到頁面卡頓

比如我們建立一個回調,内部包含static靜态變量,然後裡面也傳入了Context,假設在Activity的OnClick時間内構造它,那麼每一次構造都會有Context - XXXActivity對象被儲存在這個回調的内部,那麼每一次finish都不會釋放。

當我們打開AndroidStudio的Memory Profiler的時候我們就可以在Memory裡面看到成階梯狀的記憶體消耗的趨勢。這個時候我們通過記憶體變化曲線(階梯狀)可以判斷記憶體存在洩漏。

App體系化優化之記憶體優化(Memory Analyzer Tool + Memory Profiler)

我們隻需要把我們認為有洩漏的部分,進行堆轉儲,導出檔案即可

(華為手機 eg P40,當我們使用Memory Profiler的時候會閃退,可能是ROM架構的問題)

接下來,将導出檔案轉換:

hprof-conv /xxxx/memory_leak.hprof /xxxxx/memory_leak_transed.hprof  不執此指令MAT不能處理堆轉儲檔案

1.打開檔案

點選Histogram

App體系化優化之記憶體優化(Memory Analyzer Tool + Memory Profiler)

2.比對搜尋需要的類的名稱

App體系化優化之記憶體優化(Memory Analyzer Tool + Memory Profiler)
App體系化優化之記憶體優化(Memory Analyzer Tool + Memory Profiler)

我們可以看見有一個Activity存在存在七個對象 這是不合理的

那麼來看看都是誰強引用了吧

App體系化優化之記憶體優化(Memory Analyzer Tool + Memory Profiler)

看見了七個強引用

App體系化優化之記憶體優化(Memory Analyzer Tool + Memory Profiler)

選擇一個對象  去除軟引用 隻關注強引用 也可以直接看with all references

App體系化優化之記憶體優化(Memory Analyzer Tool + Memory Profiler)

檢視強引用結果的依賴路徑

App體系化優化之記憶體優化(Memory Analyzer Tool + Memory Profiler)

我們可以看見是EventBus中持有了上下文的引用看看源碼

App體系化優化之記憶體優化(Memory Analyzer Tool + Memory Profiler)

銷毀的時候寫錯了,應該改成

@Override
protected void onDestroy() {
    super.onDestroy();
    if (EventBus.getDefault().isRegistered(this)) {
        //取消注冊
        EventBus.getDefault().unregister(this);
    }
}
           

這樣就釋放了。雖然隻是一個複制粘貼的問題,但是卻真實的影響了性能,不會崩潰,線上上是一個很惡心的bug,回報到研發這裡隻是偶現。這就是通過記憶體分析查找問題的方法 MAT+MemoryProfiler

前後對比

App體系化優化之記憶體優化(Memory Analyzer Tool + Memory Profiler)
App體系化優化之記憶體優化(Memory Analyzer Tool + Memory Profiler)

可以看見記憶體得到了釋放~~~~~~~~

繼續閱讀