Leakcanary(一)

它是什么

一句話說驶臊,就是:

Android項目中豪治,用于檢測內(nèi)存泄露,優(yōu)化性能的工具

解決了什么問題

解決了,內(nèi)存泄漏難以發(fā)現(xiàn)的問題讼积。通過Leakcanary肥照,可以輕松的找到GC中跟搜索法可達,然而不再使用的對象勤众。
一般情況下舆绎,這種問題是很難被發(fā)現(xiàn)的,原因是他的出現(xiàn)是不經(jīng)意間的们颜,其中吕朵,內(nèi)存泄露常見的場景有:

內(nèi)存泄露常見場景

非靜態(tài)內(nèi)部類的靜態(tài)實例

  1. 非靜態(tài)內(nèi)部類會持有外部類的引用
  2. 在外部類生命周期結(jié)束后,靜態(tài)實例會長期維持著外部類的引用窥突,導致無法被gc

多線程相關(guān)的匿名內(nèi)部類\非靜態(tài)內(nèi)部類

  1. 匿名內(nèi)部類同樣也會持有外部類實例的引用努溃,例如(AsyncTask、Tread阻问、Runnable接口的實現(xiàn)類)
  2. 匿名內(nèi)部類\非靜態(tài)內(nèi)部類中有耗時操作梧税,在外部類生命周期結(jié)束后,仍然長時間維持著外部類的引用称近,導致無法被gc

Handler內(nèi)存泄露

  1. Handler定義為非靜態(tài)的第队,即持有了外部引用
  2. Message存儲到MessageQueue中,耗時較長刨秆,無法被回收

怎樣去使用它

集成進項目之中

  1. 新版本的Leakcanary只需添加依賴,無需更改代碼

    debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.5'
    

發(fā)現(xiàn)內(nèi)存泄露

Leaknary 能夠發(fā)現(xiàn)內(nèi)存泄露的位置有:

  • 銷毀的Activity 實例
  • 銷毀的Fragment 實例
  • 銷毀的View 實例
  • 銷毀的ViewModel 實例
    LeakCanary可以hook到Android生命周期中凳谦,從而自動檢測Activity和Fragment何時destroy,并進行垃圾收集衡未。ObjectWatcher持有這些被destroy的對象的弱引用尸执。通過以下方法,可以找到被Destroy的對象眠屎,例如
AppWatcher.objectWatcher.watch(myDetachedView, "View was detached")

如果運行垃圾回收剔交,并等待5秒鐘后ObjectWatcher仍未清除 肆饶,則認定可能發(fā)生內(nèi)存泄漏改衩。LeakCanary將此記錄到Logcat:


在未被正常清楚的對象達到一定數(shù)量后,LeakCanary將其dump到存儲堆驯镊,并顯示通知:
圖1.LeakCanary找到了4個未被正常清楚的對象葫督。

注意:

當應用程序的狀態(tài)是可見的時候,默認閾值為5 板惑,當應用程序是不可見的時候橄镜,默認閾值為1,冯乘。如果看到Leakcanary彈出通知洽胶,然后將應用程序壓至后臺(例如,直接上劃進入主頁)裆馒,則LeakCanary閾值從5更改為1姊氓,并在5秒鐘后dump到存儲堆丐怯。若點擊按鈕將強制LeakCanary立即dump到存儲堆。

打印堆中的信息

當保留對象的數(shù)量達到閾值時翔横,LeakCanary將Java堆dump到存儲在Android文件系統(tǒng)上的.hprof文件中(詳見LeakCanary在何處存儲堆轉(zhuǎn)儲读跷?)。轉(zhuǎn)儲堆會使應用程序停止運行一小段時間禾唁,在此期間LeakCanary會顯示Toast:

圖2.LeakCanary顯示了在堆放時的Toast

分析堆中的信息

LeakCanary.hprof使用Shark解析文件效览,并在該堆存儲中找到保留的對象。

圖3.LeakCanary在堆存儲中查找保留的對象荡短。

對于每個保留的對象丐枉,LeakCanary會查找引用路徑,以防止對該保留的對象進行垃圾回收:至于泄露跟蹤的具體內(nèi)容掘托,將在下一部分中展開:修復內(nèi)存泄漏矛洞。
圖4.LeakCanary計算每個保留對象的泄漏跟蹤

分析完成后,LeakCanary將顯示帶有摘要的通知烫映,并在Logcat中顯示結(jié)果沼本。注意:下圖將4個保留的對象歸為2個不同的泄漏。LeakCanary為每個泄漏跟蹤創(chuàng)建一個簽名锭沟,并將具有相同簽名的泄漏(即抽兆,由同一bug引起的泄漏)組合在一起。
圖5. 4條泄漏跡線變成2個不同的泄漏特征族淮。

點擊彈出的通知辫红,將提供更多詳細的信息。也可以通過啟動Leaks來找到該條內(nèi)存泄露的詳細信息
圖6.LeakCanary為安裝的每個應用程序添加一個啟動器圖標祝辣。

在Leaks中贴妻,每行對應一組具有相同簽名的泄漏。應用程序首次出現(xiàn)的內(nèi)存泄露類型將標記為“New”蝙斜。
圖7.將4個泄漏分組為2行名惩,每個泄漏標記對應一個

點擊泄漏將展示整個泄露的跟蹤信息。
圖8. 顯示了3個同一類別的內(nèi)存泄露

泄漏簽名是每個級聯(lián)的散列參考懷疑導致泄漏孕荠,即娩鹉,每個參考與紅色下劃線顯示:
圖9.帶有3個可疑參考的泄漏跟蹤。

當泄漏跟蹤以文本形式共享時稚伍,這些相同的可疑引用都帶有下劃線:如

并計算出響應的signature 弯予,例如上述的簽名為

分類內(nèi)存泄露信息

常見的內(nèi)存泄露Leaknary將其分成了第三方庫和程序員操作失誤兩種。

  1. 第三方庫的泄露如下所示:(帶有Library Leak)


    圖10.LeakCanary發(fā)現(xiàn)了Library Leak个曙。
  2. 程序員異常操作的泄露:


    圖10.NewsFragment.mRootV處泄露

如何解決內(nèi)存泄露

  1. 我們在代碼中能不用static變量持有context就不用锈嫩,非要用就用weak引用。
  2. 對于內(nèi)部類,盡量用靜態(tài)內(nèi)部類呼寸,這樣就不會持有外部類引用那槽。如果需要外部類引用做一些事,就手動賦給一個weak引用等舔。
  3. 對于匿名內(nèi)部類骚灸,不要圖簡單方便,實在不行就 寫成外部類
  4. 在使用handler時慌植,記得在activity的onDestroy()中加上remove()甚牲,有待嘗試
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市蝶柿,隨后出現(xiàn)的幾起案子丈钙,更是在濱河造成了極大的恐慌,老刑警劉巖交汤,帶你破解...
    沈念sama閱讀 222,729評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件雏赦,死亡現(xiàn)場離奇詭異,居然都是意外死亡芙扎,警方通過查閱死者的電腦和手機星岗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來戒洼,“玉大人俏橘,你說我怎么就攤上這事∪剑” “怎么了寥掐?”我有些...
    開封第一講書人閱讀 169,461評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長磷蜀。 經(jīng)常有香客問我召耘,道長,這世上最難降的妖魔是什么褐隆? 我笑而不...
    開封第一講書人閱讀 60,135評論 1 300
  • 正文 為了忘掉前任污它,我火速辦了婚禮,結(jié)果婚禮上妓灌,老公的妹妹穿的比我還像新娘轨蛤。我一直安慰自己,他們只是感情好虫埂,可當我...
    茶點故事閱讀 69,130評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著圃验,像睡著了一般掉伏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,736評論 1 312
  • 那天斧散,我揣著相機與錄音供常,去河邊找鬼。 笑死鸡捐,一個胖子當著我的面吹牛栈暇,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播箍镜,決...
    沈念sama閱讀 41,179評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼源祈,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了色迂?” 一聲冷哼從身側(cè)響起香缺,我...
    開封第一講書人閱讀 40,124評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎歇僧,沒想到半個月后图张,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,657評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡诈悍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,723評論 3 342
  • 正文 我和宋清朗相戀三年祸轮,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片侥钳。...
    茶點故事閱讀 40,872評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡倔撞,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出慕趴,到底是詐尸還是另有隱情痪蝇,我是刑警寧澤,帶...
    沈念sama閱讀 36,533評論 5 351
  • 正文 年R本政府宣布冕房,位于F島的核電站躏啰,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏耙册。R本人自食惡果不足惜给僵,卻給世界環(huán)境...
    茶點故事閱讀 42,213評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望详拙。 院中可真熱鬧帝际,春花似錦、人聲如沸饶辙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽弃揽。三九已至脯爪,卻和暖如春则北,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背痕慢。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評論 1 274
  • 我被黑心中介騙來泰國打工尚揣, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人掖举。 一個月前我還...
    沈念sama閱讀 49,304評論 3 379
  • 正文 我出身青樓快骗,卻偏偏與公主長得像,于是被迫代替她去往敵國和親塔次。 傳聞我的和親對象是個殘疾皇子方篮,可洞房花燭夜當晚...
    茶點故事閱讀 45,876評論 2 361

推薦閱讀更多精彩內(nèi)容