美文网首页一些收藏
LeakCanary的工作原理

LeakCanary的工作原理

作者: 三十五岁养老 | 来源:发表于2022-03-03 16:48 被阅读0次

    Java四大引用

    • 强引用:绝不回收
    • 软引用:内存不足才回收
    • 弱引用:碰到就回收
    • 虚引用:等价于没有引用,只是用来标识下指向的对象是否被回收。

    WeakReference类

    弱引用, 当一个对象仅仅被weak reference(弱引用)指向, 而没有任何其他strong reference(强引用)指向的时候, 如果这时GC运行, 那么这个对象就会被回收,不论当前的内存空间是否足够,这个对象都会被回收

    WeakReference继承Reference,其中只有两个构造函数:

     /**
         * Creates a new weak reference that refers to the given object.  The new
         * reference is not registered with any queue.
         *
         * @param referent object the new weak reference will refer to
         */
        public WeakReference(T referent) {
            super(referent);
        }
     /**
         * Creates a new weak reference that refers to the given object and is
         * registered with the given queue.
         *
         * @param referent object the new weak reference will refer to
         * @param q the queue with which the reference is to be registered,
         *          or <tt>null</tt> if registration is not required
         */
        public WeakReference(T referent, ReferenceQueue<? super T> q) {
            super(referent, q);
        }
    
    • referent:被弱引用的对象,
    • ReferenceQueue:应用队列,在对象被回收后,会把弱引用对象,也就是WeakReference对象或者其子类的对象,放入队列ReferenceQueue中,注意不是被弱引用的对象,被弱引用的对象已经被回收了。
    private void test() {
        // 创建一个对象(强引用)
        Object obj = new Object();
        // 创建一个弱引用,并指向这个对象,并且将引用队列传递给弱引用
        WeakReference<Object> reference = new WeakReference(obj, queue);
       
        // gc一次看看
        System.gc();
        此时循环打印引用队列为null
       
        while ((obj = queue.poll()) != null) {
            System.out.println(": " + obj);
        }
        // 设置obj为null,现在只有弱引用引用,可以被回收了
        obj = null;
        // 再进行gc,此时obj应该被回收了,那么queue里面应该有这个弱引用了
        System.gc();
        // 再打印队列不为
        Object obj;
        while ((obj = queue.poll()) != null) {
            System.out.println(": " + obj);
        }
    }
    

    LeakCanary工作原理

    利用弱引用特性,检测Activity 的内存泄漏

    • LeakCanary.install(application);此时使用application进行registerActivityLifecycleCallbacks,从而来监听Activity的何时被destroy。

    • 在onActivityDestroyed(Activity activity)的回调中, 使用一个弱引用WeakReference指向这个activity,并且给这个弱引用指定一个引用队列queue,同时创建一个key来标识该activity。

    • 然后将检测的方法ensureGone()投递到空闲消息队列。

    • 当空闲消息执行的时候,去检测queue里面是否存在刚刚的弱引用,如果存在,则说明此activity已经被回收,就移除对应的key,没有内存泄漏发生。

    • 如果queue里不存在刚刚的弱引用,则手动进行一次gc。

    • gc之后再次检测queue里面是否存在刚刚的弱引用,如果不存在,则说明此activity还没有被回收,此时已经发生了内存泄漏,直接dump堆栈信息并打印日志,否则没有发生内存泄漏,流程结束。

    空闲消息被执行的时候,大概率已经发生过gc,所以可以检测下gc后activity是否被回收。但是也可能还没发生gc,那么此时activity没有被回收是正常的,所以我们手动再gc一下,确保发生了gc,再去检测activity是否被回收,从而100%的确定是否发生了内存泄漏。

    相关文章

      网友评论

        本文标题:LeakCanary的工作原理

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