LeakCanary

LeakCanary原理浅析

1.LeakCanary简介

LeakCanary是一个Android和Java的内存泄漏检测库,可以大幅可以大幅度减少了开发中遇到的OOM问题。

LeakCanary开源库的地址为:LeakCanary开源库

LeakCanary的README地址如下:LeakCanary的README

2.如何使用LeakCanary

使用LeakCanary非常简单,只需要在Application的onCreate()方法里面调用LeakCanary.install(this)方法,就像下面一样:

public class ExampleApplication extends Application {

    @Override 
    public void onCreate() {
        super.onCreate();
        // 如果是在HeapAnalyzer进程里,则返回,因为该进程是专门用来堆内存分析的。
        if (LeakCanary.isInAnalyzerProcess(this)) {
            // This process is dedicated to LeakCanary for heap analysis.
            // You should not init your app in this process.
            return;
        }
        //调用LeakCanary.install()的方法来进行必要的初始化工作,来监听内存泄漏。
        LeakCanary.install(this);
        // Normal app init code...
    }
}

如果只想检测Activity的内存泄漏,而且只想使用默认的报告方式,则只需按照上面的实例,在Application里面添加一行代码:

LeakCanary.install(this);

如果想监控Fragment等其他有生命周期函数的方法的类是否有内存泄漏时,可以先返回一个RefWatcher对象,然后通过RefWatcher监控那些本该被回收的对象。使用示例如下:

public class ExampleApplication 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);
    }
}

使用RefWatcher监控Fragment:

public abstract class BaseFragment extends Fragment {

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

可以看到,不管哪种方式,都需要调用LeakCanary.install()方法,因此接下来的源码分析将从这个方法开始。

3.LeakCanary源码分析

第一部分:初始化工作

先来看下LeakCanary初始化工作时序图:

LeakCanary初始化时序图

接下来将从LeakCanary的install()方法开始分析LeakCanary的工作流程。

3.1 LeakCanary.install()

/*
* 创建一个RefWatcher,用来监控Activity的引用
*/
public static RefWatcher install(Application application) {
    return refWatcher(application).listenerServiceClass(DisplayLeakService.class)
        .excludedRefs(AndroidExcludedRefs.createAppDefaults().build())
        .buildAndInstall();//见3.2,3.3,3.4
}

refWatcher(application)方法返回的是一个AndroidRefWatcherBuilder,通过这个Builder来配置RefWatcher的一些设置参数。

public static AndroidRefWatcherBuilder refWatcher(Context context) {
    return new AndroidRefWatcherBuilder(context);
}

3.2 AndroidRefWatcherBuilder.listenerServiceClass()

/*
* 设置一个自定义的AbstractAnalysisResultService服务来监听内存分析结果
*/
public AndroidRefWatcherBuilder listenerServiceClass(
  Class<? extends AbstractAnalysisResultService> listenerServiceClass) {
    return heapDumpListener(new ServiceHeapDumpListener(context, listenerServiceClass));
}

通过ServiceHeapDumpListener类来保存listenerServiceClass服务,然后再通过RefWatcherBuilder来保存HeapDump的listener。

public ServiceHeapDumpListener(Context context,
  Class<? extends AbstractAnalysisResultService> listenerServiceClass) {
    setEnabled(context, listenerServiceClass, true);
    setEnabled(context, HeapAnalyzerService.class, true);
    this.listenerServiceClass = checkNotNull(listenerServiceClass, "listenerServiceClass");//保存listenerServiceClass
    this.context = checkNotNull(context, "context").getApplicationContext();
}

public final T heapDumpListener(HeapDump.Listener heapDumpListener) {
    this.heapDumpListener = heapDumpListener;//保存HeapDump的listener
    return self();
}

可以看到,listenerServiceClass()方法主要保存监听内存分析结果的listener,当内存分析结果完成后,则回调该listener,在这里这个listener是DisplayLeakService服务。

3.3 RefWatcherBuilder.excludedRefs()

/*
* 该方法主要是排除一些开发可以忽略的泄漏路径(一般是系统级别BUG),这些枚举在AndroidExcludedRefs这个类当中定义 
*/
public final T excludedRefs(ExcludedRefs excludedRefs) {
    this.excludedRefs = excludedRefs;
    return self();
}

由于AndroidRefWatcherBuilder继承自RefWatcherBuilder,excludedRefs()方法只在RefWatcherBuilder类中定义,因此调用的是RefWatcherBuilder.excludedRefs()方法,该方法的主要作用是告诉需要忽略哪些已知的系统泄漏Bug,避免这些结果产生干扰。

3.4 AndroidRefWatcherBuilder.buildAndInstall()

/*
* 创建一个RefWatcher实例,并且开始监控Activity实例引用
*/
public RefWatcher buildAndInstall() {
    RefWatcher refWatcher = build();//构建一个RefWatcher,见3.5
    // 如果RefWatcher可用,则让泄漏通知显示服务生效,并且注册监听。
    if (refWatcher != DISABLED) {
        LeakCanary.enableDisplayLeakActivity(context);
        ActivityRefWatcher.install((Application) context, refWatcher);//注册监听,见3.6
    }
    return refWatcher;
}

该方法的主要作用是构建一个RefWatcher类,并判断RefWatcher是否可用,如果可用的话,则让泄漏通知显示服务生效,并且注册监听。

3.5 RefWatcherBuilder.build()

/*
* 构建一个RefWatcher对象
*/
public final RefWatcher build() {
    //如果禁用了,则返回
    if (isDisabled()) {
        return RefWatcher.DISABLED;
    }
    // 保留被排出系统的泄漏Bug
    ExcludedRefs excludedRefs = this.excludedRefs;
    if (excludedRefs == null) {
        excludedRefs = defaultExcludedRefs();
    }
    // 保存HeapDump的listener,监听内存分析结果
    HeapDump.Listener heapDumpListener = this.heapDumpListener;
    if (heapDumpListener == null) {
        heapDumpListener = defaultHeapDumpListener();
    }
    // 保存调试控制,如果是处理调试阶段,则忽略内存泄漏监控
    DebuggerControl debuggerControl = this.debuggerControl;
    if (debuggerControl == null) {
        debuggerControl = defaultDebuggerControl();
    }
    // 保存HeapDumper,如果没有定义,则使用默认的HeapDumper,为AndroidHeapDumper。
    HeapDumper heapDumper = this.heapDumper;
    if (heapDumper == null) {
        heapDumper = defaultHeapDumper();
    }
    // 保存WatchExecutor,如果没有定义,则使用默认的WatchExecutor,为AndroidWatchExecutor。
    WatchExecutor watchExecutor = this.watchExecutor;
    if (watchExecutor == null) {
        watchExecutor = defaultWatchExecutor();
    }

    // 保存GcTrigger,如果没有定义,则使用默认的GcTrigger,为GcTrigger.DEFAULT
    GcTrigger gcTrigger = this.gcTrigger;
    if (gcTrigger == null) {
        gcTrigger = defaultGcTrigger();
    }

    return new RefWatcher(watchExecutor, debuggerControl, gcTrigger, heapDumper, heapDumpListener,
    excludedRefs);//调用RefWatcher的构造方法,保留设置的参数
}

RefWatcher(WatchExecutor watchExecutor, DebuggerControl debuggerControl, GcTrigger gcTrigger,
    HeapDumper heapDumper, HeapDump.Listener heapdumpListener, ExcludedRefs excludedRefs) {
    this.watchExecutor = checkNotNull(watchExecutor, "watchExecutor");
    this.debuggerControl = checkNotNull(debuggerControl, "debuggerControl");
    this.gcTrigger = checkNotNull(gcTrigger, "gcTrigger");
    this.heapDumper = checkNotNull(heapDumper, "heapDumper");
    this.heapdumpListener = checkNotNull(heapdumpListener, "heapdumpListener");
    this.excludedRefs = checkNotNull(excludedRefs, "excludedRefs");
    retainedKeys = new CopyOnWriteArraySet<>();//保存key的集合
    queue = new ReferenceQueue<>();//引用队列
}

可以看到build()方法主要是根据之前设置的一些参数来构建RefWatcher对象,如果有参数没有初始化,则使用默认的配置参数来初始化。在RefWatcher中,还有两个比较关键的成员,分别是retainedKeys和queue,他们在后面判断一个对象是否泄漏将会被用到。

3.6 ActivityRefWatcher.install()

/*
* 注册监听
*/
public static void install(Application application, RefWatcher refWatcher) {
    new ActivityRefWatcher(application, refWatcher).watchActivities();//见3.7
}

该方法首先是创建一个ActivityRefWatcher对象,该对象用来确保Activity被销毁的时候不会泄漏。接着调用watchActivities()来监控Activity实例是否泄漏了。

public ActivityRefWatcher(Application application, RefWatcher refWatcher) {
    this.application = checkNotNull(application, "application");
    this.refWatcher = checkNotNull(refWatcher, "refWatcher");
}

3.7 ActivityRefWatcher.watchActivities()

public void watchActivities() {
    // Make sure you don't get installed twice.
    stopWatchingActivities();//避免两次重复注册
    application.registerActivityLifecycleCallbacks(lifecycleCallbacks);//调用Application的registerActivityLifecycleCallbacks()方法,该方法只在Android 4.0以后才支持,见3.8
}

watchActi

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值