Android內存泄漏檢測利器:LeakCanary

Android內存泄漏檢測利器:LeakCanary

是什么?

一言以蔽之:LeakCanary是一個傻瓜化并且可視化的內存泄露分析工具

為什么需要LeakCanary慨代?

因為它簡單,易于發(fā)現(xiàn)問題扒腕,人人可參與寞钥。

  • 簡單:只需設置一段代碼即可,打開應用運行一下就能夠發(fā)現(xiàn)內存泄露雷激。而MAT分析需要Heap Dump,獲取文件告私,手動分析等多個步驟侥锦。
  • 易于發(fā)現(xiàn)問題:在手機端即可查看問題即引用關系,而MAT則需要你分析德挣,找到Path To GC Roots等關系恭垦。
  • 人人可參與:開發(fā)人員,測試測試,產品經理基本上只要會用App就有可能發(fā)現(xiàn)問題番挺。而傳統(tǒng)的MAT方式唠帝,只有部分開發(fā)者才有精力和能力實施。

如何集成

盡量在app下的build.gradle中加入以下依賴

在Application中加入類似如下的代碼

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

到這里你就可以檢測到Activity的內容泄露了玄柏。其實現(xiàn)原理是設置Application的ActivityLifecycleCallbacks方法監(jiān)控所有Activity的生命周期回調襟衰。內部實現(xiàn)代碼為

public final class ActivityRefWatcher {
    private final ActivityLifecycleCallbacks lifecycleCallbacks = new ActivityLifecycleCallbacks() {
        public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
        }

        public void onActivityStarted(Activity activity) {
        }

        public void onActivityResumed(Activity activity) {
        }

        public void onActivityPaused(Activity activity) {
        }

        public void onActivityStopped(Activity activity) {
        }

        public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
        }

        public void onActivityDestroyed(Activity activity) {
            ActivityRefWatcher.this.onActivityDestroyed(activity);
        }
    };
    private final Application application;
    private final RefWatcher refWatcher;

    public static void installOnIcsPlus(Application application, RefWatcher refWatcher) {
        if(VERSION.SDK_INT >= 14) {
            ActivityRefWatcher activityRefWatcher = new ActivityRefWatcher(application, refWatcher);
            activityRefWatcher.watchActivities();
        }
    }
....
}

想要檢測更多?

首先我們需要獲得一個RefWatcher,用來后續(xù)監(jiān)控可能發(fā)生泄漏的對象

public class MyApplication extends Application { 
private static RefWatcher sRefWatcher;    
@Override    public void onCreate() {        
    super.onCreate();        
    sRefWatcher = LeakCanary.install(this);
    }    
  public static RefWatcher getRefWatcher() {        
    return sRefWatcher;  
  }
}

監(jiān)控某個可能存在內存泄露的對象

MyApplication.getRefWatcher().watch(sLeaky);

哪些需要進行監(jiān)控

默認情況下粪摘,是對Activity進行了檢測瀑晒。另一個需要監(jiān)控的重要對象就是Fragment實例。因為它和Activity實例一樣可能持有大量的視圖以及視圖需要的資源(比如Bitmap)即在Fragment onDestroy方法中加入如下實現(xiàn)

public class MainFragment extends Fragment {    
  @Override    
  public void onDestroy() {        
    super.onDestroy();        
    MyApplication.getRefWatcher().watch(this);    
  }
}

何時進行監(jiān)控

首先徘意,我們需要明確什么是內存泄露苔悦,簡而言之,某個對象在該釋放的時候由于被其他對象持有沒有被釋放椎咧,因而造成了內存泄露玖详。

因此,我們監(jiān)控也需要設置在對象(很快)被釋放的時候勤讽,如Activity和Fragment的onDestroy方法蟋座。

一個錯誤示例,比如監(jiān)控一個Activity脚牍,放在onCreate就會大錯特錯了向臀,那么你每次都會收到Activity的泄露通知。

解決方案

常用的解決方法思路如下

  • 盡量使用Application的Context而不是Activity的
  • 使用弱引用或者軟引用
  • 手動設置null诸狭,解除引用關系
  • 將內部類設置為static飒硅,不隱式持有外部的實例
  • 注冊與反注冊成對出現(xiàn),在對象合適的生命周期進行反注冊操作作谚。
  • 如果沒有修改的權限,比如系統(tǒng)或者第三方SDK庵芭,可以使用反射進行解決持有關系

如何實現(xiàn)的

LeakCanary實際上就是在本機上自動做了Heap dump妹懒,然后對生成的hprof文件分析,進行結果展示双吆。和手工進行MAT分析步驟基本一致眨唬。

實踐中的問題

  • 如果targetSdkVersion為23,在6.0的機器上會存在問題好乐,卡死匾竿,因為LeakCanary并沒有很好支持Marshmallow運行時權限,所以始終得不到sd卡權限蔚万,進而導致卡死岭妖。

注意

  • 目前LeakCanary一次只能報一個泄漏問題,如果存在內存泄漏但不是你的模塊,并不能說明這個模塊沒有問題昵慌。建議建議將非本模塊的泄漏解決之后假夺,再進行檢測。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末斋攀,一起剝皮案震驚了整個濱河市已卷,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌淳蔼,老刑警劉巖侧蘸,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異鹉梨,居然都是意外死亡讳癌,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門俯画,熙熙樓的掌柜王于貴愁眉苦臉地迎上來析桥,“玉大人,你說我怎么就攤上這事艰垂∨菡蹋” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵猜憎,是天一觀的道長娩怎。 經常有香客問我,道長胰柑,這世上最難降的妖魔是什么截亦? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮柬讨,結果婚禮上崩瓤,老公的妹妹穿的比我還像新娘。我一直安慰自己踩官,他們只是感情好却桶,可當我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蔗牡,像睡著了一般颖系。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上辩越,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天嘁扼,我揣著相機與錄音,去河邊找鬼黔攒。 笑死趁啸,一個胖子當著我的面吹牛强缘,可吹牛的內容都是我干的。 我是一名探鬼主播莲绰,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼欺旧,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蛤签?” 一聲冷哼從身側響起辞友,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎震肮,沒想到半個月后称龙,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡戳晌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年鲫尊,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片沦偎。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡疫向,死狀恐怖,靈堂內的尸體忽然破棺而出豪嚎,到底是詐尸還是另有隱情搔驼,我是刑警寧澤,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布侈询,位于F島的核電站舌涨,受9級特大地震影響,放射性物質發(fā)生泄漏扔字。R本人自食惡果不足惜囊嘉,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望革为。 院中可真熱鬧扭粱,春花似錦、人聲如沸震檩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽恳蹲。三九已至,卻和暖如春俩滥,著一層夾襖步出監(jiān)牢的瞬間嘉蕾,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工霜旧, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留错忱,地道東北人儡率。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像以清,于是被迫代替她去往敵國和親儿普。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內容