Android 内存泄漏检测利器 LeakCanary
开源工具:https://github.com/square/leakcanary
官方文档:https://square.github.io/leakcanary/
最新版本:2.0
1.引入依赖库
2.操作应用
3.如果有内存泄漏,通知栏会有消息,点击通知栏可获取到具体内存泄漏信息
4.也可以从手机中拉取 hprof 文件,使用 Android studio 的 profile 工具进行定位分析
1.引入依赖库
最新版本的 leakcanary 不需要插入任何代码,仅仅需要添加 build.gradle 中加入以下依赖即可:
dependencies {
// debugImplementation 使得仅仅debug版apk才会进行内存泄漏分析 debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.0'
}
2.点击通知栏消息获取内存泄漏信息
以下举个例子,APP 中在 MainActivity 跳转到 Main2Activity,在 Main2Activity 中给自定义单例类 TestLeak 的 getInstance 方法传入了 Main2Activity 的 context,由于 TestLeak 中的 tl 是一个 static 静态对象,声明周期同 Application 一样长,当从 Main2Activity 跳转回 MainActivity 时,Main2Activity 需要被销毁,但是 TestLeak 中的 tl 依然持有 Main2Activity 的 context,导致 Main2Activity 无法被回收,而发生内存泄漏。
public class TestLeak {
private static TestLeak tl;
private Context context;
private TestLeak(Context context) {
this.context = context;
}
//导致了内存泄漏
public static TestLeak getInstance(Context context) {
if (tl == null) {
tl = new TestLeak(context);
// tl = new TestLeak(context.getApplicationContext());
}
return tl;
}
}
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void newPage(View view) {
Intent intent = new Intent(this, Main2Activity.class);
startActivity(intent);
}
}
public class Main2Activity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
TestLeak testLeak= TestLeak.getInstance(this);
}
}
操作 APP 从 MainActivity 跳转到 Main2Activity,再返回 MainActivity,查看手机通知栏如下:
点击通知栏后,如下:
由上图可以清晰的看到内存泄漏发生的位置。
3.分析 hprof 文件定位问题
对于复杂问题可以借助 Android studio 的 profile 工具进行定位分析,从上图中的” heap dump file path” 拿到 hrop 文件,打开后如下所示:
上图中 Heap Dump 右边四列的意思分别如下:
Allocations:Java 堆中的实例个数
Native Size:native 层分配的内存大小
Shallow Size:Java 堆中分配实际大小
Retained Size:这个类的所有实例保留的内存总大小
注:在内存泄漏检查的过程中,一般如果 Shallow Size 和 Retained Size 都非常小并且相等,都可以认为是已经被回收的对象。因为系统已经不认为它会被用到,并且没有给它保留分配的内存。如果出现上述图中 Retained Size 远远大于 Shallow Size 的情况下,就很有可能出现了内存泄漏。
使用 leakcanary 进行内存泄漏检查,有明显的优势就是对工程中的代码没有任何的侵入,发生内存泄漏后展示的消息可以清楚的定位到问题所在。笔者认为也有一点点缺点那就是内存泄漏发现的时间点相对有些滞后,不能记录问题发生的步骤,复现问题依然困难。