什么是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);
}
}
然后屏幕会发出一个提示框
然后再通知栏会收到一条通知,如果是第一次使用,会先请求写入权限,点击,并允许
然后过一段时间,通知栏会出现新的通知,点进去就是内存泄漏的引用链
我们看到MessageQueue中的mMessages中的target持有MainActivity的引用,这个target就是我们MainActivity当中的匿名实现的成员变量Handler,从而得知内存泄露的原因
LeakCanary在检测到内存泄露的同时,除了弹出通知,还会将堆内存dump成hprof文件放在我们的应用所属的file文件夹下面(十分钟之内,只会写入一次)
如果我们想要详细的分析,就需要借助MAT工具,来分析hprof文件
hprof文件
转换成MAT可识别的文件
cd到sdk/tools的路径下,执行命令 hprof-conv hprof路径 输出路径
得到mat可识别的文件
MAT
下载地址:http://www.eclipse.org/mat/downloads.php
win版安装之后如下,点击运行MemoryAnalyzer.exe
点击右上角菜单File - OpenHeapDump - 刚刚转换后的hprof文件
右键这个条目 —— Path to GC roots —— with all references
referent是LeakCanary保存的对Activity的引用
this$0就是内部类所自动保留的一个指向所在外部类的引用
很明显是this$0导致了我们内存的泄露,也就是mMessages中的target,也就是Handler