全面总结Android内存泄漏(下)

参考资料:
Android 内存泄漏总结
Android内存泄漏小谈

你真的懂 Java 的内存管理和引用类型吗?
Android 性能优化:手把手带你全面了解内存泄露
[贝聊科技]使用Android Studio和MAT进行内存泄漏分析
【Android 性能优化】—— 详解内存优化的来龙去脉
Android 关于内存泄露,你必须了解的东西
Android性能优化系列之内存优化
Android 内存泄漏案例和解析
Android 内存泄漏分析心得
Android开发常见的Activity中内存泄漏及解决办法
Android内存泄漏查找和解决
Android 内存泄漏全解
彻底搞懂Java内存泄漏
简析Android的垃圾回收与内存泄露
Android应用内存泄漏的定位、分析与解决策略
Android 性能优化 - 彻底解决内存泄漏
利用Android Studio、MAT对Android进行内存泄漏检测
Android内存泄漏学习笔记

接上篇,分析了内存泄漏产生的原因和常见的内存泄漏之后,我们就应该采用一些方案来检测我们代码中可能产生内存泄漏的地方。下面是常用的检测方案。

LeakCanary


github地址:

https://github.com/square/leakcanary

Wiki:

https://github.com/square/leakcanary/wiki

首先引入:

1
2
3
4
dependencies {
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.4'
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.4'
}

然后在app的application中:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class ExampleApplication extends Application {

@Override public void onCreate() {
super.onCreate();
if (LeakCanary.isInAnalyzerProcess(this)) {
// This process is dedicated to LeakCanary for heap analysis.
// You should not init your app in this process.
return;
}
LeakCanary.install(this);
// Normal app init code...
}
}

应用运行起来后,LeakCanary会自动去分析当前的内存状态(需要sd卡读写权限)。然后稍等片刻(需要一定的时间来分析),如果检测到泄漏会发送到通知栏,点击通知栏就可以跳转到具体的泄漏分析页面,可以看到泄漏的内存的引用链。like this:

上面的代码仅仅是LeakCanary的初级使用,只能检测Activity中的内存泄漏,想要更进阶的用法最好还是参考官方Wiki, 或者是先看一下技术小黑屋的这篇Android内存泄漏检测利器:LeakCanary

Memory Analyzer (MAT)

MAT 是 Eclipse 出品的一个插件,当然也有独立的版本。下载链接:MAT 下载地址
下面我举例介绍MAT的使用方法。
首先写个会发生内存泄漏的activity

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class HandlerLeakActivity extends AppCompatActivity implements OnClickListener {

private TextView mTextView;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
System.out.println("===== handle message ====");
}
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler_leak);
mTextView = findViewById(R.id.tv);
mTextView.setOnClickListener(this);
}

@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.tv:
mHandler.sendEmptyMessageDelayed(0x12, 60 * 1000L);
finish();
break;
}
}

}

将app运行起来,然后切到Monitors

先点击点击几次那个像卡车一样的图标(Initiate GC)进行gc, 等待几秒之后点击它右边的图标(Dump Java Heap),然后便会生成Java Heap文件

从这里大致可以看到是HandlerLeakActivity发生了内存泄漏,接着点击左边的“Captures”, 然后右键,导出成标准的.hprof文件

使用MAT打开

点击“Leak Suspects”检查泄漏

切换到支配树视图,根据前面的提示,是HandlerLeakActivity发生了泄漏,于是搜索到那个Activity, 对着 HandlerLeakActivity 对象点击右键 -> Merge Shortest Paths to GC Roots(当然,这里也可以选择 Path To GC Roots) -> exclude all phantom/weak/soft etc. references为什么选择 exclude all phantom/weak/soft etc. references 呢?因为弱引用等是不会阻止对象被垃圾回收器回收的,所以我们这里直接把它排除掉

从下图已经看到内存泄漏发生的引用链了

更多的使用方法,看看官方的Tutorials或者这篇吧[贝聊科技] 使用 Android Studio 和 MAT 进行内存泄漏分析

Allocation Tracker

该工具用途:

  • 可以定位代码中分配的对象类型、大小、时间、线程、堆栈等信息;
  • 可以定位内存抖动问题;
  • 配合 Heap Viewer 定位内存泄露问题(可以找出来泄露的对象是在哪创建的等等)。
    如果我们想了解内存分配更详细的情况, 可以使用 Allocation Traker 来查看内存到底被什么占用了

    使用方法:在 Memory Monitor 中有个 Start Allocation Tracking 按钮即可开始跟踪 在点击停止跟踪后会显示统计结果。

    当你想查看某个方法的源码时, 右键选择的方法, 点击 Jump to source 就可以了。
    对于Allocation Tracker,我也不是很熟悉,感兴趣可以参考这两篇文章中介绍的
    【Android 性能优化】—— 详解内存优化的来龙去脉
    Android 性能优化系列之内存优化

更多分析内存的工具

  • Heap Viewer

该工具用于:
显示内存快照信息;
每次 GC 后收集一次信息;
查找内存泄露的利器。
使用方法:
在 Memory Monitor 中有个 Dump Java Heap 按钮,点击即可,在统计报告左上角选按 package 分类。配合 Memory Monitor 的 initiate GC(执行 GC)按钮,可检测内存泄露等情况。
详细请自行查询。

更多工具可以参考一下这篇
Android 应用内存泄漏的定位、分析与解决策略

总结

总的来说,我觉得一般LeakCanary和MAT就够用了,配合上Android Studio的自带的Monitors已经很好用了

0%