使用新版Android Studio檢測記憶體洩露和效能

yangxi_001發表於2016-07-08

記憶體洩露,是Android開發者最頭疼的事。可能一處小小的記憶體洩露,都可能是毀於千里之堤的蟻穴。
怎麼才能檢測記憶體洩露呢?網上教程非常多,不過很多都是使用Eclipse檢測的, 其實1.3版本以後的Android Studio 檢測記憶體非常方便, 如果結合上MAT工具,LeakCanary外掛,一切就變得so easy了。

熟悉Android Studio介面

工欲善其事,必先利其器。我們接下來先來熟悉下Android Studio的介面
這裡寫圖片描述

一般分析記憶體洩露, 首先執行程式,開啟日誌控制檯,有一個標籤Memory ,我們可以在這個介面分析當前程式使用的記憶體情況, 一目瞭然, 我們再也不需要苦苦的在logcat中尋找記憶體的日誌了。

圖中藍色區域,就是程式使用的記憶體, 灰色區域就是空閒記憶體,
當然,Android記憶體分配機制是對每個應用程式逐步增加, 比如你程式當前使用30M記憶體, 系統可能會給你分配40M, 當前就有10M空閒, 如果程式使用了50M了,系統會緊接著給當前程式增加一部分,比如達到了80M, 當前你的空閒記憶體就是30M了。 當然,系統如果不能再給你分配額外的記憶體,程式自然就會OOM(記憶體溢位)了。 每個應用程式最高可以申請的記憶體和手機密切相關,比如我當前使用的華為Mate7,極限大概是200M,算比較高的了, 一般128M 就是極限了, 甚至有的手機只有可憐的16M或者32M,這樣的手機相對於記憶體溢位的概率非常大了。

我們怎麼檢測記憶體洩露呢

首先需要明白一個概念, 記憶體洩露就是指,本應該回收的記憶體,還駐留在記憶體中。
一般情況下,高密度的手機,一個頁面大概就會消耗20M記憶體,如果發現退出介面,程式記憶體遲遲不降低的話,可能就發生了嚴重的記憶體洩露。
我們可以反覆進入該介面,然後點選dump java heap 這個按鈕,然後Android Studio就開始幹活了,下面的圖就是正在dump
這裡寫圖片描述

dump成功後會自動開啟 hprof檔案,檔案以Snapshot+時間來命名
這裡寫圖片描述

通過Android Studio自帶的介面,檢視記憶體洩露還不是很智慧,我們可以藉助第三方工具,常見的工具就是MAT了,下載地址 http://eclipse.org/mat/downloads.php ,這裡我們需要下載獨立版的MAT. 下圖是MAT一開始開啟的介面, 這裡需要提醒大家的是,MAT並不會準確地告訴我們哪裡發生了記憶體洩漏,而是會提供一大堆的資料和線索,我們需要自己去分析這些資料來去判斷到底是不是真的發生了記憶體洩漏。

這裡寫圖片描述

接下來我們需要用MAT開啟記憶體分析的檔案, 上文給大家介紹了使用Android Studio生成了 hprof檔案, 這個檔案在呢, 在Android Studio中的Captrues這個目錄中,可以找到
這裡寫圖片描述

注意,這個檔案不能直接交給MAT, MAT是不識別的, 我們需要右鍵點選這個檔案,轉換成MAT識別的。
這裡寫圖片描述

然後用MAT開啟匯出的hprof(File->Open heap dump) MAT會幫我們分析記憶體洩露的原因
這裡寫圖片描述
這裡寫圖片描述

LeakCanary

上面介紹了MAT檢測記憶體洩露, 再給大家介紹LeakCanary。
專案地址:https://github.com/square/leakcanary

LeakCanary會檢測應用的記憶體回收情況,如果發現有垃圾物件沒有被回收,就會去分析當前的記憶體快照,也就是上邊MAT用到的.hprof檔案,找到物件的引用鏈,並顯示在頁面上。這款外掛的好處就是,可以在手機端直接檢視記憶體洩露的地方,可以輔助我們檢測記憶體洩露
這裡寫圖片描述

使用:
在build.gradle檔案中新增,不同的編譯使用不同的引用:

dependencies { 
    debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3' 
    releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3' 
}

在應用的Application onCreate方法中新增LeakCanary.install(this),如下

public class ExampleApplication extends Application 
    @Override 
    public void onCreate() {
        super.onCreate(); 
        LeakCanary.install(this);
     }
 }

應用執行起來後,LeakCanary會自動去分析當前的記憶體狀態,如果檢測到洩漏會傳送到通知欄,點選通知欄就可以跳轉到具體的洩漏分析頁面。
Tips:就目前使用的結果來看,絕大部分洩漏是由於使用單例模式hold住了Activity的引用,比如傳入了context或者將Activity作為listener設定了進去,所以在使用單例模式的時候要特別注意,還有在Activity生命週期結束的時候將一些自定義監聽器的Activity引用置空。
關於LeakCanary的更多分析可以看專案主頁的介紹,還有這裡http://www.liaohuqiu.net/cn/posts/leak-canary-read-me/

追蹤記憶體分配

如果我們想了解記憶體分配更詳細的情況,可以使用Allocation Traker來檢視記憶體到底被什麼佔用了。
用法很簡單:
這裡寫圖片描述

點一下是追蹤, 再點一下是停止追蹤, 停止追蹤後 .alloc檔案會自動開啟,開啟後介面如下:
這裡寫圖片描述
當你想檢視某個方法的原始碼時,右鍵選擇的方法,點選Jump to source就可以了

查詢方法執行的時間

Android Studio 功能越來越強大了, 我們可以藉助AS觀測各種效能,如下圖:
這裡寫圖片描述

如果我們要觀測方法執行的時間,就需要來到CPU介面
這裡寫圖片描述

點選Start Method Tracking, 一段時間後再點選一次, trace檔案被自動開啟,
這裡寫圖片描述

非獨佔時間: 某函式佔用的CPU時間,包含內部呼叫其它函式的CPU時間。
獨佔時間: 某函式佔用CPU時間,但不含內部呼叫其它函式所佔用的CPU時間。

我們如何判斷可能有問題的方法?

通過方法的呼叫次數和獨佔時間來檢視,通常判斷方法是:

  1. 如果方法呼叫次數不多,但每次呼叫卻需要花費很長的時間的函式,可能會有問題。
  2. 如果自身佔用時間不長,但呼叫卻非常頻繁的函式也可能會有問題。

綜述

上面給大家介紹了若干使用Android Studio檢查程式效能的工具,工具永遠是輔助,不要因為工具耽誤太長時間。如果有問題,歡迎大家糾正。

相關文章