Android内存泄露检测工具 LeakCanary 使用 及 MAT分析

什么是LeakCanary

LeakCanary是# square公司推出的专为Android设计的内存泄露检测库

如何集成

官方github地址:https://github.com/square/leakcanary

使用步骤很简单,下面简单把官方步骤翻译一下

1,在build.gradle文件中引入依赖
dependencies {
  debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.5.4'
  releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.4'
}
2,在Application的onCreate方法中引入
public class ExampleApplication extends Application {

  @Override public void onCreate() {
    super.onCreate();
    if (LeakCanary.isInAnalyzerProcess(this)) {
      // 这个线程是专门给LeakCanary做堆内存分析的
      // 在这里不要写app初始化代码
      return;
    }
    LeakCanary.install(this);
    // 在这里写你app的初始化代码
  }
}

到目前为止,LeakCanary已经集成到你的项目中
如果APP的Android编译版本>=4.0版本,那么LeakCanary已经可以自动检测内存泄露了
因为4.0之后Application提供了registerActivityLifecycleCallbacks方法,可以给全局的activity生命周期加入回调,至于原因,我们在源码解析篇进行分析

模拟一个内存泄露

一个比较常见的场景:

Handler作为成员变量接受一个匿名内部类的实现,onCreate方法中,发布一个延时任务,60秒后执行
,然后手动关闭Activity

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    Handler handler = new Handler(){
        @Override
        public void dispatchMessage(Message msg) {
            super.dispatchMessage(msg);
            //do something
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        handler.sendEmptyMessageDelayed(0,60 * 1000);
    }
}

然后屏幕会发出一个提示框


Android内存泄露检测工具 LeakCanary 使用 及 MAT分析_第1张图片
image.png

然后再通知栏会收到一条通知,如果是第一次使用,会先请求写入权限,点击,并允许


Android内存泄露检测工具 LeakCanary 使用 及 MAT分析_第2张图片
image.png

然后过一段时间,通知栏会出现新的通知,点进去就是内存泄漏的引用链


Android内存泄露检测工具 LeakCanary 使用 及 MAT分析_第3张图片
image.png
Android内存泄露检测工具 LeakCanary 使用 及 MAT分析_第4张图片
image.png

我们看到MessageQueue中的mMessages中的target持有MainActivity的引用,这个target就是我们MainActivity当中的匿名实现的成员变量Handler,从而得知内存泄露的原因

LeakCanary在检测到内存泄露的同时,除了弹出通知,还会将堆内存dump成hprof文件放在我们的应用所属的file文件夹下面(十分钟之内,只会写入一次)

如果我们想要详细的分析,就需要借助MAT工具,来分析hprof文件

hprof文件

Android内存泄露检测工具 LeakCanary 使用 及 MAT分析_第5张图片
image.png

转换成MAT可识别的文件

cd到sdk/tools的路径下,执行命令 hprof-conv hprof路径 输出路径


image.png

得到mat可识别的文件


Android内存泄露检测工具 LeakCanary 使用 及 MAT分析_第6张图片
image.png

MAT

下载地址:http://www.eclipse.org/mat/downloads.php

win版安装之后如下,点击运行MemoryAnalyzer.exe


Android内存泄露检测工具 LeakCanary 使用 及 MAT分析_第7张图片
image.png
Android内存泄露检测工具 LeakCanary 使用 及 MAT分析_第8张图片
image.png

点击右上角菜单File - OpenHeapDump - 刚刚转换后的hprof文件

Android内存泄露检测工具 LeakCanary 使用 及 MAT分析_第9张图片
image.png
Android内存泄露检测工具 LeakCanary 使用 及 MAT分析_第10张图片
image.png
Android内存泄露检测工具 LeakCanary 使用 及 MAT分析_第11张图片
image.png
Android内存泄露检测工具 LeakCanary 使用 及 MAT分析_第12张图片
image.png

右键这个条目 —— Path to GC roots —— with all references

Android内存泄露检测工具 LeakCanary 使用 及 MAT分析_第13张图片
image.png
Android内存泄露检测工具 LeakCanary 使用 及 MAT分析_第14张图片
image.png

referent是LeakCanary保存的对Activity的引用
this$0就是内部类所自动保留的一个指向所在外部类的引用

很明显是this$0导致了我们内存的泄露,也就是mMessages中的target,也就是Handler

你可能感兴趣的:(Android内存泄露检测工具 LeakCanary 使用 及 MAT分析)