內存泄露自動探測神器——LeakCanary

今天刷微博,發(fā)現各位Android開源大神都在轉發(fā)一條關于Square開源的自動探測內存泄露庫LeakCanary的信息。


LeakCanary
LeakCanary

自動探測內存泄露,這也太牛逼了吧!進入@扔物線110 分享的鏈接了解了下,對原文作簡單翻譯:(翻譯水平有限,湊合看吧-_-)

原文:https://corner.squareup.com/2015/05/leak-canary.html
LeakCanary開源庫地址:https://github.com/square/leakcanary

LeakCanary:探測所有內存泄露!

java.lang.OutOfMemoryError
        at android.graphics.Bitmap.nativeCreate(Bitmap.java:-2)
        at android.graphics.Bitmap.createBitmap(Bitmap.java:689)
        at com.squareup.ui.SignView.createSignatureBitmap(SignView.java:121)

沒有人喜歡OOM錯誤的出現

在Square Register應用中,我們實現在一個位圖緩存bitmap cache中讓客戶簽名draw the customer's signature,這個bitmap占據設備屏幕的大小,當我們創(chuàng)建一個bitmap時,會出現一個很嚴重的OOM問題。

signature
signature

我們試過幾種方法,但是沒有一種可以解決這個問題:

  • 使用 Bitmap.Config.ALPHA_8 (一種不需要顏色的簽名)
  • 捕捉OOM錯誤,觸發(fā)GC,并重試幾次(由GCUtils想起的)
  • 我們并不打算脫離Java heap分配位圖內存。對于我們幸運的是,開源圖片處理庫Fresco至今不存在這個問題

其實,我們一直以一個錯誤的方式思考這個問題了
這個bitmap的尺寸不是問題所在。當內存幾乎滿時,OOM隨時會發(fā)生。OOM常會發(fā)生在你創(chuàng)建大對象如bitmap的地方。OOM出現是一個更深層次問題內存泄露的征兆。

什么是內存泄露(memory leak)?

一些對象有有限的使用期,當它們的工作完成后,它們預期會被當作內存垃圾回收。如果一個持有對象的引用鏈結束了它的預期壽命,這將會產生一個內存泄露。隨著泄露的積累,應用程序將會耗盡內存。
例如,Activity的onDestroy()被調用后,這個Activity的視圖層次和相關的位圖都應該進行垃圾回收。而如果一個線程在后臺運行這個Activity的引用,那么相應的內存將不能被回收,這最終就導致了OutOfMemoryError的出現。

搜尋內存泄露(memory leaks)

搜尋內存泄露是一個手動過程,在Raizlabs上的Wrangling Dalvik系列文章中得到很好的描述。

這里是關鍵步驟:

  • 通過Bugsnag, Crashlytics或Google的Developer Console了解OOM問題;
  • 嘗試重現問題。你需要想盡辦法找到出現內存泄露的設備(You might need to buy, borrow, or steal the specific device that suffered the crash.) 不是所有設備都有內存泄露問題?;蛘吣阋残枰约褐谱鲀却嫘孤丁?/li>
  • 當OOM出現時進行堆轉儲(dump the heap);
  • 使用MAT或YourKit內存檢測工具檢測內存的變化,并找出哪個對象應該被垃圾回收;
  • 從那個對象到GC roots推斷最短的強引用路徑;
  • 在路徑中找出不存在的引用,并修復memory leak;
  • 要是有一個庫能夠在程序出現OOM前做這些檢測,讓你專注于解決內存泄露,那該多好呀?
    (注:好,LeakCanary正能做到!)

LeakCanary的介紹

LeakCanary是一個在調試時就可以檢測內存泄露的Java開源庫。

看個cat類的例子:

class Cat {
}
class Box {
  Cat hiddenCat;
}
class Docker {
  static Box container;
}

// ...

Box box = new Box();
Cat schrodingerCat = new Cat();
box.hiddenCat = schrodingerCat;
Docker.container = box;

創(chuàng)建一個Refwatcher的實例并傳入一個Cat對象:

// We expect schrodingerCat to be gone soon (or not), let's watch it.
refWatcher.watch(schrodingerCat);

當泄露被檢測到時,可以自動地獲取到泄露的地方:

* GC ROOT static Docker.container
* references Box.hiddenCat
* leaks Cat instance

我們知道你正忙著寫功能,所以我們使LeakCanary更容易地設置。只用一行代碼,LeakCanary就可以自動檢測活躍的泄露。

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

當內存不足時,會有一個通知和良好的展示界面:

notification
notification

總結:

使用LeakCanary后,我們在我們的app中發(fā)現并修復了很多內存泄露問題,我們甚至發(fā)現了一些Android SDK自身的內存泄露。
有了LeakCanary的結果是驚人的,我們現在減少了94%的OOM錯誤。


如果你想消除OOM引起的崩潰,[現在就安裝LeakCanary吧](If you want to eliminate OOM crashes, install LeakCanary now!)!

注:搜索資料時,發(fā)現Hacker Newsreddit上開發(fā)者對LeakCanary滿滿的贊言,Square(電子現金支付公司)確實是非常棒的一家公司,Github上有很多優(yōu)秀的開源項目,如okhttp, dagger, picasso, otto, retrofit等。技術型驅動的公司就是贊!

第一次翻譯才知道自己的英語有多渣o(╯□╰)o, 做技術的,英語水平低確實是一個瓶頸,好好加油吧!

From: 內存泄露自動探測神器——LeakCanary

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容