LeakCanary原理?

前言

依稀记得有场面试问过这个问题。虽然已经忘记是哪场面试,这里还是做一个记录和学习。

我们都知道使用LeakCanary这个第三方依赖主要是为了避免内存泄露问题。

当应用异常退出的时候,我们为了重现问题,通常需要去寻找特定的机型。但实际上并不怎么现实,且手段比较粗暴。

我们希望在发生内存泄露的时候,可以把内存 Dump 出来。然后就可以借助MAT 等工具来进行内存分析,确定哪里代码的引用不是必须的。

LeakCanary只需要集成进去,就可以检测内存泄露。

1. LeakCanary的使用案例

首先在gradle文件中引入依赖:

debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.3'

然后写第二个启动的Activity,在这个类中写一个会导致内存泄漏的BUG代码,如下:

public class TestActivity extends AppCompatActivity {
    
    
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test);
        InnerClass.getInstance(this);
    }

    // 静态单例内部类,来持有context,导致回退后不能被释放
    static class InnerClass{
    
    
        private static InnerClass mInnerClass;
        private Context context;  // 持有外部的context
        private InnerClass(Context context){
    
    
            this.context = context;
        }

        public static InnerClass getInstance(Context context){
    
    
            if(mInnerClass == null){
    
    
                mInnerClass = new InnerClass(context);
            }
            return mInnerClass;
        }
    }
}

然后可以在第一个Activity中设置点击后启动TestActivity,然后进入后就回退,返回到第一个Activity中。首先使用AndroidStudio自带的Profiler可以进行内存分析,可以发现内存泄漏问题,如下:
在这里插入图片描述
但是此时的LeakCanary还是没有提示,当多操作几轮发现最终LeakCanary有了具体的提示,如下:
在这里插入图片描述
从上面可以看出泄漏位置。但个人感觉还是没有自带的Profiler分析的快,但比较直观。

至于Profiler工具怎么使用,在我的上篇博客:Android中的性能优化方法中有比较详细的说明,这里不再复述。

2. LeakCanary原理

可以看下LeakCanary官网的介绍。
在这里插入图片描述
在这里插入图片描述

发现官网中正好有解释:How LeakCanary works?

分为四步:

  • Detecting retained objects. 使用钩子来关联Android的生命周期,检测在Activity或者Fragment被销毁的时候哪些对象应该被GC。如果这些弱引用对象在5秒后没有被GC,那么这些对象被认为是保留的。
  • Dumping the heap. 当保留对象达到了阈值,LeakCanaryJava 堆信息(heap dump)转储到 Android 文件系统的文件中,通常叫做.hprof
  • Analyzing the heap. 对每一个保留对象,LeakCanary从找到它的引用路径,即泄漏追踪。
  • Categorizing leaks.

Thanks

おすすめ

転載: blog.csdn.net/qq_26460841/article/details/120303745