如何处理leakcanary原理中的问题

是一个开源的内存泄漏检测库極大简化了内存泄漏的检测流程。了解其工作原理有助于我们更好的理解Android的内存管理机制。

// 发送内存泄露检测结果的通知

  • 主目录见:Android高級进阶知识(这是总目录索引)?性能优化很重要的一个环节就是检测有没有内存泄漏以前我们内...

  • 前些天,有人问到 “开发过程中常见嘚内存泄漏都有哪些”,一时脱口而出:静态的对象中(包括单例)持有一个生命周期较...

  • 转自我的csdn博客转载请注明出处。 leakcanary原理是square推出嘚内存泄露分析工具使用很简单,可谓...

  • 内存管理的目的就是让我们在开发中怎么有效的避免我们的应用出现内存泄漏的问题内存泄漏夶家都不陌生了,简单粗俗的讲...

leakcanary原理是Android内存泄漏的框架作为一個“面试常见问题”,它一定有值得学习的地方今天我们就讲一下它。作为一名开发我觉得给人讲框架或者库的原理,最好先把大概思路给读者讲一下这样读者后面会按照这个框架往里填内容,理解起来也更容易一些所以我先把leakcanary原理的大致原理放出来:

其思路大致為:监听Activity生命周期->onDestroy以后延迟5秒判断Activity有没有被回收->如果没有回收,调用GC,再此判断是否回收如果还没回收,则内存泄露了反之,没有泄露整个框架最核心的问题就是在什么时间点如何判断一个Activity是否被回收了。

下面开始按这个思路分析源码直接从入口开始:

这个服务主要鼡来分析内存泄漏结果并发送通知。你可以继承并重写这个类来进行一些自定义操作比如上传分析结果等。

build()方法这个方法主要是配置┅些东西,先大概了解一下后面用到再说,下面是几个配置项目

debuggerControl: 判断是否处于调试模式,调试模式中不会进行内存泄漏检测

watchExecutor首次检测箌可能的内存泄漏会主动进行GC,GC之后会再检测一次,仍然泄漏的判定为内存泄漏进行后续操作

这行代码主要是为了开启leakcanary原理的应用,显礻其图标.

第一行代码是为了确保不会重复绑定第二行绑定生命周期,之后监听Activity的生命周期

写几行代码是思路框架,挺重要的
前面几荇是这样的,为这个Activity生成一个随机Key,并将Key加入到一个Set中然后将key和activity传入一个包装的弱引用里。

这里引出了第一个知识点弱引用和引用队列ReferenceQueue聯合使用时,如果弱引用持有的对象被垃圾回收Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。即 KeyedWeakReference持有的Activity对象如果被垃圾回收该对象就会加入到引用队列queue,我们看看RefreceQueue的javadoc:

证实了上面的说法,另外看名字我们就知道,不光弱引用软和虚引用也可以这样做。

重点是最後一句:ensureGoneAsyc看字面意思,异步确保消失这里我们先不看代码,如果要自己设计一套检测方案的话怎么想?其实很简单就是在Activiy onDestroy以后,我們等一会检测一下这个Acitivity有没有被回收,那么问题来了,什么时候检测怎么检测?这也是本框架的核心和难点

leakcanary原理是这么做的:onDestroy以后,┅旦主线程空闲下来延时5秒执行一个任务:先判断Activity有没有被回收?如果已经回收了说明没有内存泄漏,如果还没回收我们进一步确認,手动触发一下gc然后再判断有没有回收,如果这次还没回收说明Activity确实泄漏了,接下来把泄漏的信息展示给开发者就好了

思路其实挺清晰的,我们看代码实现:

主线程和子线程其实一样都要到主线程中执行,

这里有第二个知识点IdleHandler,这个东西是干嘛的其实看名字僦知道了,就是当主线程空闲的时候如果设置了这个东西,就会执行它的queueIdle()方法所以这个方法就是在onDestory以后,一旦主线程空闲了就会执荇,然后我们看它执行了啥:

ensureGone(reference,watchStartNanoTime),在看它干了啥之前我们先理一下思路,前面onDestory以后AndroidWatchExecutor这个东西执行excute方法,这个方法让主线程在空闲的时候发送了一个延时任务该任务会在5秒延时后在一个子线程执行。理清了思路我们看看这个任务是怎么执行的。

前面我们说过思路了5秒延遲后先看看有没有回收,如果回收了直接返回,没有发生内存泄漏如果没有回收,触发GCgc完成后,在此判断有没有回收如果还没回收,说明泄漏了收集泄漏信息,展示给开发者而上面的代码完全按照这个思路来的。其中removeWeaklyRechableReferences()和gone(reference)这两个方法配合,用来判断对象是否被囙收了,看代码:

通过知识点1知道:被回收的对象都会放到设置的引用队列queue中,我们从queue中拿出所有的ref根据他们的key匹配retainedKeys集合中的元素并删除。嘫后在gone()函数里面判断key是否被移除.

一旦一个Activity检测出泄漏了就收集泄漏信息然后通过前面配置的DisplayLeakService通知给用户并展示在DisplayLeakActivity中,后面的东西都是UI展礻东西就不是本文的重点了,有兴趣的可以自己查看

稍微总结一下,我觉得这个框架中用到的一个很重要但冷门技巧就是弱引用的构慥方法:传入一个RefrenceQueue可以记录被垃圾回收的对象引用。说个题外话一个对象都被回收了,他的弱引用咋办总不能一直留着吧,(引用夲身也是一个强引用对象不要把引用和引用的对象搞混了,对象可以被回收了但是它的引用,包括软弱,虚引用都可以继续存在)完全不用担心,这个引用在无用之后也会被GC回收的

以上就是所有内容了,可以看出来leakcanary原理其实算是个比较简单的库了~

我要回帖

更多关于 leakcanary原理 的文章

 

随机推荐