Android 内存泄漏分析工具

在上篇文章中了解了什么是「Android 开发中的内存泄漏」,这篇来记录一下在 Android App 开发中可以用什么工具来帮助开发者发现以及消除内存泄漏

Android Studio Profiler 工具

Android Studio 作为官方的 Android App 开发 IDE,功能越来越强大,从 Android Studio 3.0 开始提供 Profiler 来对 App 的 CPU、内存、网络、电量进行检测,帮助开发者发现 App 运行时潜在的问题 Android Studio Profiler

如何使用

首先模拟一下内存泄漏场景

MainActivity

public class MainActivity extends AppCompatActivity {
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		findViewById(R.id.btn_jump).setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
			    //从 MainActivity 跳转到 SecondActivty
				startActivity(new Intent(MainActivity.this, SecondActivity.class));
			}
		});

	}
}
复制代码

SecondActivity

public class SecondActivity extends AppCompatActivity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_second);

		//非静态匿名内部类发送延迟消息,然后立即点击返回按钮
		new Handler().postDelayed(new Runnable() {
			@Override
			public void run() {
				System.out.println();
			}
		}, 10_000);
	}
}
复制代码

捕获堆转存 发现内存泄漏

可以看到左上角检测到两个 Leaks ,依次按下图点击,可以清晰的打印出内存泄漏的引用链: 显示引用链

Eclipse Memory Analyzer (www.eclipse.org/mat/)

这是个 Eclipse 提供的内存分析工具,功能比 Profiler 丰富,但操作难度也高,但能更清晰的分析内存快照

首先通过 Profiler - Capture heap dump 获取内存快照,然后点击 Heap Dump 右边的保存按钮将一个 hprof 文件保存的本地,此文件无法直接使用,需要使用 Android sdk 下 /platform-tools/hprof-conv 命令进行转换,如下

hprof-conv demo.hprof demo-conv.hprof
复制代码

通过 MAT 打开 demo-conv.hprof 文件,依次点击 overview - histogram:

预览 柱状图

以上面的内存泄漏为例,可以通过正则搜索「SecondActivity」,然后右键搜索结果,选择 Merge Shortest Paths to GC Roots -> exclude all phantom/weak/soft etc.references 排除所有非强引用链:

内存中的对象 可以看到 Message 持有了 Handler 的引用,而 Handler 持有 SecondActivity 的引用,导致内存泄漏

小技巧

mat 还支持比较两个 hprof 文件,所以可以通过比较 dump 打开某个页面前后的内存快照,来判断哪些对象没有释放

LeakCanary (square.github.io/leakcanary/)

LeakCanary 是大名鼎鼎的 Square 团队开发的,他们还开发了 Okhttp、Retrofit 等热门的开源框架

以上是比较简单的内存泄漏场景,而实际的开发环境要复杂很多,都需要开发者主动去检测内存泄漏,而 LeakCanary 通过观察 Activity 、Fragment、ViewModel、Service 等组件的生命周期,LeakCanary 可以及时检测到 App 是否有内存泄漏,并随着功能的迭代,已经可以非常清晰的打印出引用链来更快速的帮助开发者定位代码位置。

猜你喜欢

转载自juejin.im/post/7077743165809098760