全面總結Android記憶體洩漏(下)

mundane發表於2018-02-23

本文章首發於個人部落格

參考資料:
Android 記憶體洩漏總結
Android記憶體洩漏小談
你真的懂 Java 的記憶體管理和引用型別嗎?
Android 效能優化:手把手帶你全面瞭解記憶體洩露
[貝聊科技]使用Android Studio和MAT進行記憶體洩漏分析

【Android 效能優化】—— 詳解記憶體優化的來龍去脈
Android 關於記憶體洩露,你必須瞭解的東西
Android效能優化系列之記憶體優化
Android 記憶體洩漏案例和解析

Android 記憶體洩漏分析心得

Android開發常見的Activity中記憶體洩漏及解決辦法
Android記憶體洩漏查詢和解決
Android 記憶體洩漏全解

徹底搞懂Java記憶體洩漏

簡析Android的垃圾回收與記憶體洩露

Android應用記憶體洩漏的定位、分析與解決策略
Android 效能優化 - 徹底解決記憶體洩漏
利用Android Studio、MAT對Android進行記憶體洩漏檢測
Android記憶體洩漏學習筆記

接上篇,分析了記憶體洩漏產生的原因和常見的記憶體洩漏之後,我們就應該採用一些方案來檢測我們程式碼中可能產生記憶體洩漏的地方。下面是常用的檢測方案。

LeakCanary

全面總結Android記憶體洩漏(下)

github地址:

https://github.com/square/leakcanary

Wiki:

https://github.com/square/leakcanary/wiki

首先引入:

dependencies {
  debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.4'
  releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.4'
}
複製程式碼

然後在app的application中:

public class ExampleApplication extends Application {

  @Override public void onCreate() {
    super.onCreate();
    if (LeakCanary.isInAnalyzerProcess(this)) {
      // This process is dedicated to LeakCanary for heap analysis.
      // You should not init your app in this process.
      return;
    }
    LeakCanary.install(this);
    // Normal app init code...
  }
}
複製程式碼

應用執行起來後,LeakCanary會自動去分析當前的記憶體狀態(需要sd卡讀寫許可權)。然後稍等片刻(需要一定的時間來分析),如果檢測到洩漏會傳送到通知欄,點選通知欄就可以跳轉到具體的洩漏分析頁面,可以看到洩漏的記憶體的引用鏈。like this: 全面總結Android記憶體洩漏(下) 上面的程式碼僅僅是LeakCanary的初級使用,只能檢測Activity中的記憶體洩漏,想要更進階的用法最好還是參考官方Wiki, 或者是先看一下技術小黑屋的這篇Android記憶體洩漏檢測利器:LeakCanary

Memory Analyzer (MAT)

MAT 是 Eclipse 出品的一個外掛,當然也有獨立的版本。下載連結:MAT 下載地址 下面我舉例介紹MAT的使用方法。 首先寫個會發生記憶體洩漏的activity

public class HandlerLeakActivity extends AppCompatActivity implements OnClickListener {

    private TextView mTextView;
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            System.out.println("===== handle message ====");
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handler_leak);
        mTextView = findViewById(R.id.tv);
        mTextView.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.tv:
                mHandler.sendEmptyMessageDelayed(0x12, 60 * 1000L);
                finish();
                break;
        }
    }

}
複製程式碼

將app執行起來,然後切到Monitors 全面總結Android記憶體洩漏(下) 先點選點選幾次那個像卡車一樣的圖示(Initiate GC)進行gc, 等待幾秒之後點選它右邊的圖示(Dump Java Heap),然後便會生成Java Heap檔案 全面總結Android記憶體洩漏(下) 從這裡大致可以看到是HandlerLeakActivity發生了記憶體洩漏,接著點選左邊的“Captures”, 然後右鍵,匯出成標準的.hprof檔案 全面總結Android記憶體洩漏(下) 使用MAT開啟 全面總結Android記憶體洩漏(下) 點選“Leak Suspects”檢查洩漏 全面總結Android記憶體洩漏(下) 切換到支配樹檢視,根據前面的提示,是HandlerLeakActivity發生了洩漏,於是搜尋到那個Activity, 對著 HandlerLeakActivity 物件點選右鍵 -> Merge Shortest Paths to GC Roots(當然,這裡也可以選擇 Path To GC Roots) -> exclude all phantom/weak/soft etc. references為什麼選擇 exclude all phantom/weak/soft etc. references 呢?因為弱引用等是不會阻止物件被垃圾回收器回收的,所以我們這裡直接把它排除掉 全面總結Android記憶體洩漏(下) 從下圖已經看到記憶體洩漏發生的引用鏈了 全面總結Android記憶體洩漏(下) 更多的使用方法,看看官方的Tutorials或者這篇吧[貝聊科技] 使用 Android Studio 和 MAT 進行記憶體洩漏分析

Allocation Tracker

該工具用途:

  • 可以定位程式碼中分配的物件型別、大小、時間、執行緒、堆疊等資訊;
  • 可以定位記憶體抖動問題;
  • 配合 Heap Viewer 定位記憶體洩露問題(可以找出來洩露的物件是在哪建立的等等)。 如果我們想了解記憶體分配更詳細的情況, 可以使用 Allocation Traker 來檢視記憶體到底被什麼佔用了
    全面總結Android記憶體洩漏(下)
    使用方法:在 Memory Monitor 中有個 Start Allocation Tracking 按鈕即可開始跟蹤 在點選停止跟蹤後會顯示統計結果。 全面總結Android記憶體洩漏(下) 當你想檢視某個方法的原始碼時, 右鍵選擇的方法, 點選 Jump to source 就可以了。 對於Allocation Tracker,我也不是很熟悉,感興趣可以參考這兩篇文章中介紹的
    【Android 效能優化】—— 詳解記憶體優化的來龍去脈
    Android 效能優化系列之記憶體優化

更多分析記憶體的工具

  • Heap Viewer

該工具用於: 顯示記憶體快照資訊; 每次 GC 後收集一次資訊; 查詢記憶體洩露的利器。 使用方法: 在 Memory Monitor 中有個 Dump Java Heap 按鈕,點選即可,在統計報告左上角選按 package 分類。配合 Memory Monitor 的 initiate GC(執行 GC)按鈕,可檢測記憶體洩露等情況。 詳細請自行查詢。

更多工具可以參考一下這篇 Android 應用記憶體洩漏的定位、分析與解決策略

總結

總的來說,我覺得一般LeakCanary和MAT就夠用了,配合上Android Studio的自帶的Monitors已經很好用了

相關文章