天天看點

LeakCanary: 讓記憶體洩露無所遁形

09 May 2015

當時,我們嘗試過一些解決方案,但都沒解決問題

使用 Bitmap.Config.ALPHA_8 因為,簽名僅有黑色。

其實 bitmap 的尺寸不是真正的問題,當記憶體吃緊的時候,到處都有可能引發 OO。在建立大對象,比如 bitmap 的時候,更有可能發生。OOM 隻是一個表象,更深層次的問題可能是: 記憶體洩露。

一些對象有着有限的生命周期。當這些對象所要做的事情完成了,我們希望他們會被回收掉。但是如果有一系列對這個對象的引用,那麼在我們期待這個對象生命周期結束的時候被收回的時候,它是不會被回收的。它還會占用記憶體,這就造成了記憶體洩露。持續累加,記憶體很快被耗盡。

比如,當 <code>Activity.onDestroy</code> 被調用之後,activity 以及它涉及到的 view 和相關的 bitmap 都應該被回收。但是,如果有一個背景線程持有這個 activity 的引用,那麼 activity 對應的記憶體就不能被回收。這最終将會導緻記憶體耗盡,然後因為 OOM 而 crash。

以下幾個關鍵步驟:

重制問題。為了重制問題,機型非常重要,因為一些問題隻在特定的裝置上會出現。為了找到特定的機型,你需要想盡一切辦法,你可能需要去買,去借,甚至去偷。 當然,為了确定複現步驟,你需要一遍一遍地去嘗試。一切都是非常原始和粗暴的。

計算這個對象到 GC roots 的最短強引用路徑。

确定引用路徑中的哪個引用是不該有的,然後修複問題。

很複雜對吧?

如果有一個類庫能在發生 OOM 之前把這些事情全部都搞定,然後你隻要修複這些問題就好了,豈不妙哉!

先看一個例子:

建立一個<code>RefWatcher</code>,監控對象引用情況。

當發現有記憶體洩露的時候,你會看到一個很漂亮的 leak trace 報告:

GC ROOT static Docker.container

references Box.hiddenCat

leaks Cat instance

我們知道,你很忙,每天都有一大堆需求。是以我們把這個事情弄得很簡單,你隻需要添加一行代碼就行了。然後 LeakCanary 就會自動偵測 activity 的記憶體洩露了。

然後你會在通知欄看到這樣很漂亮的一個界面:

結果是驚豔的,我們減少了 94% 的由 OOM 導緻的 crash。

相關連結:

<a href="https://www.liaohuqiu.net/cn/posts/leak-canary-read-me/">LeakCanary 中文使用說明</a>

    本文轉自 一點點征服   部落格園部落格,原文連結:http://www.cnblogs.com/ldq2016/p/6635816.html

,如需轉載請自行聯系原作者