zoukankan      html  css  js  c++  java
  • 【Android内存泄漏检测】LeakCanary使用总结

    一、什么是LeakCanary?

    LeakCanary就是用来检测Android端内存泄漏的一个工具。能够检测Activity的泄漏

    什么是内存泄漏?

    Java 对象有时也会”长死不死“,GC 拿它没有办法,这种情况就是内存泄漏。造成这种情况的原因是:Java 对象被另一个生命周期更长对象持有,具有 可达性 ,这并不是我们想要的。

    来自 <http://www.jianshu.com/p/3f1a1cc1e964>

    内存泄漏的危害?

    内存泄漏最终将导致内存溢出,也就是OOM,并且OOM发生在某一处,并不代表问题就是出在那里的,只是刚好有一块内存申请,此时内存又不够了才导致的,比较容易出现在申请比较大的内存的情况下。但是把这块申请的内存降低并不能从根本上解决问题。

    这里有一个问题就是:内存的分配方式,分配位置,比如BitMap的分配,以及其他对象的分配?以及Activity对对象的持有,这个概念还不是很清晰。

    github上的地址:https://github.com/square/leakcanary

    一个原理的介绍内容在这里:

    https://www.liaohuqiu.net/cn/posts/leak-canary/

    https://www.liaohuqiu.net/cn/posts/leak-canary-read-me/

    二、LeakCanary的工作原理是什么?

    这三个都有讲解,并且还有直接通过源码来进行讲解的,后面可以针对这块,针对源码专门研究一下。

    http://www.jianshu.com/p/a8900eb3de12

    http://www.jianshu.com/p/5ee6b471970e

    http://www.jianshu.com/p/3f1a1cc1e964

    工作原理是:

    LeakCanary会开启一个Service,这个Service能够在一个Activity被OnDestory之后,检测是否真的还有这个对象,如果还有,会尝试进行二次确认,如果这个对象还是没有被释放掉,则会获取当时的内存状态,生成一个heap的状态文件,然后分析文件,计算这个对象的GC ROOT的最短强引用路径,确定是否泄漏,如果有泄漏,Leak的APP就会有一条通知栏消息出现

    检测流程图如下:

    三、如何使用

    1、在build.gradle中引入:

     debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3.1' // or 1.4-beta1
        releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1' // or 1.4-beta1
        testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1' // or 1.4-beta1

    或者,现在最新的1.5.1的也可以直接用:

    dependencies{

    compile'com.squareup.leakcanary:leakcanary-android:1.5.1'

    }

    2、同时,在Application的方法,在OnCreate中添加install

    public class DemoApplication extends Application {
        @Override public void onCreate() {
            super.onCreate();
            LeakCanary.install(this);
        }
    }

    3、在添加之后,直接打出来应用的包,装上之后,会看到有一个附属应用出来,名字叫做Leaks

    4、直接操作APP,如果发现有内存泄漏,则这个过程中会有通知栏提示,点击查看即可,可以将泄漏的信息分享,也可以将当时的heap dump的信息分享出来(但有可能这个heap dump不一定存在)

    以检测出来的一个图为例:

    LeakCanary的内存泄露提示一般会包含三个部分:

    第一部分(LeakSingle类的sInstance变量)引用第二部分(LeakSingle类的mContext变量), 导致第三部分(MainActivity类的实例instance)泄露.

    下方是一些更详细的原理的讲解:

    1、不同的几种引用方式:强-软-弱-虚

    2、LeakCanary这里,有一个原理的讲解叫做:

     

     

    需要理解为什么要用WeakReference,因为GC的时候是不会对强引用的做处理,而软引用的是在内存不够用了才会被回收,而弱引用就是可以随时回收,所以需要用WeakReference对待检测的对象进行包裹引用,因为是弱引用的,因此在待检测对象调用了Destory或者Finish方法之后,被WeakReference引用的对象的生命周期结束,因为这个是弱引用,就会被GC检测到,这个时候GC会把该对象添加到ReferenceQueue中,如果GC结束该对象还是没有被加入到ReferenceQueue中,则说明可能存在内存泄漏,其实就是找到所有生命周期结束的对象,过滤掉会被回收的,剩下就是没有被回收的,然后会做二次GC,之后还是没有回收,就可以找到当时的内存状态,拿到不同对象的引用情况,得到一个hprof的文件,之后就能找到最短强引用的路径。

     

    解决内存泄漏,通过以下方式:

    然后我们需要解决:如何得到未被回收的对象。ReferenceQueue+WeakReference+手动调用 GC可实现这个需求。

     

    • WeakReference 创建时,传入一个 ReferenceQueue 对象。当被 WeakReference 引用的对象的生命周期结束,一旦被 GC 检查到,GC 将会把该对象添加到 ReferenceQueue 中,待ReferenceQueue处理。当 GC 过后对象一直不被加入 ReferenceQueue,它可能存在内存泄漏。

     

    获得未被回收的 Object

    • 找到了未被回收的对象,如何确认是否真的内存泄漏?这里可以将问题转换为:未被回收的对象,是否被其他对象引用?找出其最短引用链。VMDebug + HAHA 完成需求。
      VM 会有堆内各个对象的引用情况,并能以hprof文件导出。HAHA 是一个由 square 开源的 Android 堆分析库,分析 hprof 文件生成Snapshot对象。Snapshot用以查询对象的最短引用链。

     

    解析hprof

    • 找到最短引用链后,定位问题,排查代码将会事半功倍。

    如下泳道图分析, LeakCanary 各个模块如何配合达到检测目的。

     

     

    来自 <http://www.jianshu.com/p/3f1a1cc1e964>

     

  • 相关阅读:
    笨方法学python笔记
    Orchard CMS 单点解决方案(SSO)及两种身份认证模块的介绍
    Orchard Oauth身份认证模块,在原基础上支持百度,豆瓣,开心,QQ,人人,新浪,淘宝
    凉鞋
    第一天
    网络编程vc++、socket机制
    定时器
    界面的多语言切换/通过读取xml文件实现
    svn快速教程
    文件读写
  • 原文地址:https://www.cnblogs.com/keke-xiaoxiami/p/6962584.html
Copyright © 2011-2022 走看看