美文网首页
LeakCanary

LeakCanary

作者: 壹零二肆 | 来源:发表于2020-09-17 21:31 被阅读0次

    核心:

    • 0 引用 + 内部类
    • 1 概述
    • 2 使用
    • 3 原理
    • 4 总结

    https://github.com/square/leakcanary
    https://square.github.io/leakcanary/

    “A small leak will sink a great ship.” - Benjamin Franklin

    0 引用 + 内部类

    0.1 引用

    什么是引用?

    引用可以用指针的概念来理解

    A B 两个对象 , A 内部可以调用 B 的方法就称,A内有B的引用

    即 A 内有个B的指针,可以访问到B

    0.1.1 强引用

    A a = new A();
    a 就是指向 new出对象的一个强引用
    a = null
    此时 new 出的对象就不再被a强引用
    进入垃圾回收流程

    0.1.2 软引用

    内存不够的时候,会回收发现的软引用
    此时的软引用可以被回收
    回收后会加入到关联到引用队列
    信号——内存不够

    0.1.3 弱引用

    发生gc就会回收
    弱引用的对象
    并且将回收的对象加入队列

    0.1.4 幻引用

    随时会被回收

    
    public class Refer {
        @Test
        public void main() throws Exception {
    
            Object wfOb = new Object();
            Object sfOb = new Object();
            Object pfOb = new Object();
    
            ReferenceQueue<Object> wfQ = new ReferenceQueue<>();
            ReferenceQueue<Object> sfQ = new ReferenceQueue<>();
            ReferenceQueue<Object> pfQ = new ReferenceQueue<>();
    
            WeakReference weakReference = new WeakReference<>(wfOb, wfQ);
            SoftReference softReference = new SoftReference<>(sfOb, sfQ);
            PhantomReference phantomReference = new PhantomReference<>(pfOb, pfQ);
    
            System.out.println("softReference");
            System.out.println(softReference.get() != null);
            sfOb = null;
            System.gc();
            System.out.println(softReference.get() != null);
    //        System.out.println(sfQ.poll().get() != null);
    
            System.out.println("weakReference");
            System.out.println(weakReference.get() != null);
            wfOb = null;
            System.gc();
            System.out.println(weakReference.get() != null);
            System.out.println(wfQ.poll().get() != null);
    
            System.out.println("phantomReference");
            System.out.println(phantomReference.get() != null);
            pfOb = null;
            System.gc();
            System.out.println(phantomReference.get() != null);
            System.out.println(pfQ.poll().get() != null);
    
        }
    }
    
    

    0.2 内部类

    放在类的内部(成员内部类)
    方法的内部(局部内部类)
    方法的参数内(匿名内部类)
    静态内部类

    非静态的内部类可以访问到外部类的成员或方法

    说明

    内部类中存有外部类的引用

    此时需要提防由于内部类的引用存在导致的内存泄漏

    1 概述

    雪崩时没有一片雪花是无辜的

    遇到生命周期敏感的对象

    谨慎处理赋值和引用关系

    2 使用

    添加依赖

    dependencies {
      // debugImplementation because LeakCanary should only run in debug builds.
      debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.4'
    }
    

    当泄漏对象达到 threshold 时将会有提示

    3 原理

    利用 WeakReference 监控对象生命周期

    如果 weakReference 引用的对象被回收,就可以在关联的引用队列中找到其引用

    当我们监控的Object比如 Activity 执行了 Destroy 后
    就又一个弱引用指向他,当指定时间都没有在队列中发现其时,意味着发生了泄漏

    官方文档:
    https://square.github.io/leakcanary/fundamentals-how-leakcanary-works/

    4 总结

    分析内存泄漏关键在于看 生命周期长短

    短命对象被长寿对象引用,短命对象应该被回收的时候,却被引用
    导致了内存泄漏

    生命周期长短:

    • 线程造成生命周期长

    • handler message的delay发送,存在 messageQueue内

    • 单例造成,单例的生命周期往往和进程同步,单例中引用的都不能被释放

    相关文章

      网友评论

          本文标题:LeakCanary

          本文链接:https://www.haomeiwen.com/subject/wmrcyktx.html