使用LeakCanary 来检查 Android 内存泄漏

LeakCanary: 由Square团队开发的一个用于检查Android和Java中内存泄露的开源库,Square 有篇文章介绍了开发这个库的原因。

用法

1.集成 LeakCanary 库(在Android Studio)

dependencies {
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3'
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3'
}

在 debug 版本上,集成 LeakCanary 库,并执行内存泄漏监测,而在 release 版本上,集成一个无操作的 wrapper ,这样对程序性能就不会有影响。


2.初始化LeakCanary

我们需要继承Application,在onCreate()里调用LeakCanary.install(this)LeakCanary.install() 返回一个配置好了的 RefWatcher 实例。

public class ApplicationController extends Application {

    public static RefWatcher getRefWatcher(Context context) {
        ExampleApplication application = (ExampleApplication)   context.getApplicationContext();
        return application.refWatcher;
    }

    private RefWatcher refWatcher;

    @Override public void onCreate() {
        super.onCreate();
        refWatcher = LeakCanary.install(this);
    }
}

然后,在AndroidManifest.xml注册下。

 <application
    android:name=".ApplicationController"
    android:allowBackup="true"
    android:icon="@mipmap/ic_logo"
    android:label="@string/app_name"
    android:theme="@style/AppTheme">

3.监控 Activity 泄露

我们经常把 Activity 当作为 Context 对象使用,在不同场合由各种对象引用 Activity。所以,Activity 泄漏是一个重要的需要检查的内存泄漏之一。 在Application中,我们调用LeakCanary.install(this)。 这个方法返回一个配置好了的 RefWatcher 实例。它同时安装了 ActivityRefWatcher 来监控 Activity 泄漏。所以,当我们初始化之后就可以自动监控 Activity 泄露,即当 Activity.onDestroy() 被调用之后,如果这个 Activity 没有被销毁,logcat 就会打印出信息告诉你内存泄漏发生。LeakCanary 的第一次分析可能会耗时较久,耐心等待。

比如:

* me.zeyuan.competition.ui.MainActivity has leaked:
* GC ROOT thread com.android.volley.CacheDispatcher.<Java Local> (named 'Thread-9214')
* references com.android.volley.toolbox.StringRequest.mListener
* references me.zeyuan.competition.ui.MainActivity$1.this$0 (anonymous class implements com.android.volley.Response$Listener)
* leaks me.zeyuan.competition.ui.MainActivity instance
* Reference Key: a809256e-40ee-4ad8-9216-e78aab3519c5
* Device: Xiaomi Xiaomi MI 4W cancro_wc_lte
* Android Version: 4.4.4 API: 19
* Durations: watch=5021ms, gc=141ms, heap dump=1428ms, analysis=20187ms

4.监控 Fragment 泄漏

public abstract class BaseFragment extends Fragment {

    @Override 
    public void onDestroy() {
        super.onDestroy();
        RefWatcher refWatcher =     ExampleApplication.getRefWatcher(getActivity());
        refWatcher.watch(this);
    }
}

当 Fragment.onDestroy() 被调用之后,如果这个 fragment 实例没有被销毁,那么就会从 logcat 里看到相应的泄漏信息。


5.监控其他泄漏

 ...
RefWatcher refWatcher = ExampleApplication.getRefWatcher(getActivity());
refWatcher.watch(someObject);

当 someObject 还在内存中时,就会在 logcat 里看到内存泄漏的提示。


6.更多

LeakCanary 自动检测 Activity 泄漏只支持 Android ICS 以上版本。因为 Application.registerActivityLifecycleCallbacks() 是在 API 14 引入的。如果要在 ICS 之前监测 Activity 泄漏,可以重载 Activity.onDestroy() 方法,然后在这个方法里调用 RefWatcher.watch(this) 来实现。


本参考文章:

LeakCanary中文说明

LeakCanary: 让内存泄露无所遁形

利用 LeakCanary 来检查 Android 内存泄漏