LeakCanary:檢測所有的內存泄露

pjp 9年前發布 | 41K 次閱讀 Android開發 移動開發 LeakCanary

        本文譯自:https://corner.squareup.com/2015/05/leak-canary.html(LeakCanary是由Square公司剛剛開源用于查找Android內存泄露的庫)

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)


          沒有人喜歡OutOfMemory崩潰

在Square的注冊界面,我們使用bitmap緩存繪制客戶的簽名,使用的bitmap大小等同于屏幕大小,當創建它時,我們有了大量的OOM崩潰。


我們嘗試了一些方法,但是沒有一個可以解決問題:
  • 使用Bitmap.Config.ALPHA_8(簽名不需要顏色)。
  • 捕獲OutOfMemoryError,觸發GC并多次重試(靈感來源于GCUtils)。
  • 我們沒有想過從Java 堆分配位圖,幸運的是,Fresco 也沒有。(注:Fresco是非死book用于圖片緩存的開源庫,可以關注一些)

我們曾看錯了方向

bitmap的大小并不是問題,當內存將要用完的時候,OOM可以隨處發生。它們更多的發生在你創建一個像Bitmap這種比較大的對象的情況下。OOM只是一個癥狀源自于更深層次的問題:內存泄露。

什么是內存溢出?

某些對象生命周期有限,當它們的工作完成以后,將會被回收。如果一個對象在其生命周期結束以后仍被內存中引用,將會導致內存泄露。當泄露積累過多,該應用將耗盡內存。

比如,在Activity.OnDestroy()方法被調用以后,這個activity的各種層級視圖和它們關聯的位圖都應該被回收掉,如果一個后臺運行的線程有該activity的引用,activity相對應的內存將不能被回收,這最終會導致OutOfMemoryError崩潰。

追蹤內存溢出

追蹤內存溢出是一個手動過程, Raizlabs 的  Wrangling Dalvik 對此有很好的描述。

下面是關鍵步驟:

  1. 通過 BugsnagCrashlytics,或者 Developer Console 了解內存溢出。
  2. 嘗試重現該問題。你可能需要通過購買或者借用遇到崩潰問題的特定設備。(并非所有設備都會呈現這些泄漏) !你還需要弄清楚是哪一系列操作觸發泄漏,有可能是蠻力。


  3. 當泄露發送時,記錄堆棧內容(點擊此處獲取代碼

  4. 使用MAT 或者YourKit 查看堆棧內容,并從中找出應該被回收的對象。

  5. 計算最短到 GC 根從該對象的強引用路徑

  6. 找出哪個引用路徑不應該存在,并修復內存溢出問題。

該庫會在你遇到OOM的時候完成以上全部操作,這樣你就可以專注于解決內存溢出問題了。


LeakCanary簡介

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

讓我們看一個小例子:

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;

創建一個RefWatcher實例并設計一個監聽對象
// 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 將會自動檢測活動泄漏:
public class ExampleApplication extends Application {
  @Override public void onCreate() {
    super.onCreate();
    LeakCanary.install(this);
  }
}

你會得到一個Notification和一個很好的展示界面:




總結

在使用LeakCanary以后,我們在自己的應用中發現了許多內存泄露問題,我們甚至發現了一些Android SDK的內存泄露

結果是令人驚訝的,我們的OOM錯誤減少了94%。



如果你想消滅OOM錯誤,現在就使用 LeakCanary 吧!

本文原創地址:http://blog.csdn.net/lilu_leo/article/details/45624735 轉載請聲明。
 本文由用戶 pjp 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!