LeakCanary让Android内存泄漏无处遁形

        在以前的文章中我讲到过如何使用eclipse和MAT分析内存泄漏(Android内存泄漏分析实战),但是这样的分析往往发生在内存泄漏之后,只能是亡羊补牢。那么我们能不能更早的发现内存泄漏呢?答案是肯定的,LeakCanary能够做到。延伸阅读(LeakCanary源码解析)

LeakCanary best practice

LeakCanary best practice

什么是LeakCanary

        LeakCanary是一个用于检测内存泄漏的工具,可以用于Java和Android,是由著名开源组织Square贡献。

开始使用

debug版本和realse版本用不同的依赖库。由于国内被墙的原因Maven没办法用,导致Android Studio使用不便。所以我自己整合了一个适合eclipse的LeakCanary的库,代码托管在github上面。项目地址:https://github.com/mooncong/Leakcanary-lib.git

在你的Application中

那么接下来,LeakCanary将会在debug版本中自动探测内存泄漏,当发生内存泄漏的时候就会在通知栏显示一个通知。

什么是内存泄露

对象在其生命周期内完成使命之后,我们就希望这些对象被回收掉。但是如果还存在对象的引用,那么这个对象将不会被回收的。它还会占用内存,这就造成了内存泄露。持续累加,内存很快被耗尽。

比如,当Activity.onDestroy 被调用之后,activity 以及它涉及到的 view 和相关的 bitmap 都应该被回收。但是,如果有一个后台线程持有这个 activity 的引用,那么 activity 对应的内存就不能被回收。这最终将会导致内存耗尽,然后因为 OOM 而 crash。

如何使用

使用RefWatcher监控本应该被垃圾回收器回收的对象

LeakCanary.install()返回一个预定义的RefWatcher。它将启动一个ActivityRefWatcher,在Activity.onDestroy()方法调用之后,自动探测Activity的内存泄漏。(注:只支持ICS及以后的版本,具体原因详见代码)

也可以使用RefWatcher探测Fragment泄漏

LeakCanary工作原理

  • RefWatcher.watch()创建一个KeyedWeakReference到北监控的对象。
  • 接下来,在后台线程中检测这个引用是否被清除,如果没有将会触发GC。
  • 如果引用仍然没有清除,将heap内存dump到一个.hprof的文件存放到手机系统里。
  • HeapAnalyzerService在另外一个独立的进程中启动,使用HeapAnalyzer解析heap内存通过HAHA这个项目
  • HeapAnalyzer计算出到GC ROOTs的最短强引用路径决定是否发生Leak,然后建立导致泄漏的引用链。
  • 结果被回传到应用程序进程的DisplayLeakService中,然后显示一个泄漏的通知。

    如何复制leak trace

    在logcat中可以看见leak trace

    也可以从Action bar分享leak trace和heap内存文件。

    如何修复内存泄漏?

    一旦发生内存泄漏,找出哪一个引用不应该存在。然后分析为什么它还存在。通常它是一个注册的监听器没有被反注册,或者是close()方法没有调用,一个匿名内部类持有了一个外部类的引用,等等。

    Android SDK导致的内存泄漏

    在过去的日子里,很多内存泄漏已经被修复了,但是当泄漏发生的时候,普通的应用开发很难去修复它。因此,LeakCanary已经建立了一个已知问题的列表,AndroidExcludedRefs.java。如果你发现一个新问题。请提交一个issue并附上Leak trace,reference key,设备和系统版本。要是附上heap文件的链接就更好了。在新发布的Android版本中尤其重要。你有机会帮助尽早的发现内存泄漏,那将会有益于整个Android社区。

    Leak trace之外

    有时候Leak trace不能够,可以使用MAT或者YourKit深挖dump文件。MAT使用可以参考以前的一片文章Android内存泄漏分析实战

  • 找到所有的com.squareup.leakcanary.KeyedWeakReference实例。
  • 查看他们的每一个key值。
  • 找到key字段等于LeakCanary报告的引用key的KeyedWeakReference。
  • KeyedWeakReference的referent字段就是泄漏的对象。
  • 接下来,就是动手修复了。最好是检查到 GC root 的最短强引用路径开始。
  • 保持Leak traces

    DisplayLeakActivity默认保存7个heap dumps和leak traces,可以通过下面的配置自定义。

    上传 leak trace 到服务器

    你可以改变处理完成的默认行为,将 leak trace 和 heap dump 上传到你的服务器以便统计分析。 创建一个 AbstractAnalysisResultService,最简单的就是继承 DefaultAnalysisResultService

    请确认Realse版本的应用使用RefWatcher.DISABLED

    自定义RefWatcher

    不要忘记在manifest中注册Service

    demo

    LeakCanary实战,包含eclipse整合的lib库,以及实例代码。运行代码之后,按照界面提示操作几次,稍等几秒,你将会在通知栏看到一个内存泄漏的通知。



      copyright@黑月神话,转载请注明出处:vjson.com

    LeakCanary让Android内存泄漏无处遁形》上有3条评论

    发表评论