您的位置:首页 > 移动开发 > Android开发

Android内存泄漏分析

2016-05-16 15:10 288 查看

1、前言

最近在fix 其他需求bug过程中,居然出现了OOM,程序直接挂了。第一反应是内存泄漏了,于是便开始查找原因。

2、现象

首先需要确定是不是内存泄漏,Android Studio的Memory监控(Android Monitors-> Memory)可以很好的呈现问题。

第一次打开app时,内存占用在20m左右。



连续多次关闭再打开操作,内存占用达到了90m左右,并且点击initiate GC(红色框按钮)无法回收。



由此,基本可以断定程序发生了内存泄漏。

3、内存分析

AS自带内存分析工具

Android Studio集成了一个内存分析工具,在GC按钮右边有一个Dump Java Heap按钮,可以生成当前应用的内存快照,并且提供了简单的内存引用分析。



我们可以着重搜索activity,查看下activity的引用分析,因为大部分内存泄漏都是因为activity引用被生命周期较长的对象持有,不能及时销毁导致的。搜索下可以看到,RxJavaActivity发生了内存泄漏,存在25个实例GC无法回收。继续查看引用分析,可以定位到具体泄漏的对象。Android studio自带的这个内存分析工具,有点乱,看的并不是很清晰,功能也没有那么强大,我们希望工具可以自动帮我们分析并定位到具体发生内存泄漏的位置。

MAT-专业的内存分析工具

MAT可以作为Eclipse插件使用,也可以单独使用,使用方法都类似。如果是分析的内存快照文件是Android Studio Dump出来的,还需要进行一次转换,不然MAT无法识别。转换工具,Android SDK中已经有了,具体位置:sdk路径/platform-tools/hprof-conv。转换命令:hprof-conv input.hprof out.hprof。如果是使用MAT Dump下来的内存快照,就不需要转换了。

使用MAT打开快照文件,选择Leak Suspects Report。然后打开Histogram,可以展示出快照中所有内存实例对象列表。



在Histigram中可以使用正则筛选出希望查看的内存对象,例如查看RxJavaActivity。结果和使用AS工具分析的基本一致。



右键,可以直接查看Paths to GC Roots,并且可以排除掉弱引用,软引用等内存不足时,系统可以回收掉的引用。



结果呈现比AS更加清晰,可以清楚的看到哪些对象持有了RxJavaActivity引用,导致内存泄漏,并且很容易定位到具体代码。



例如,这里的例子中可以判断出是我们在退出RxJavaActivity时,没有及时取消Subscription订阅,mSubscription对象仍然持有了RxJavaActivity的引用,最终导致RxJavaActivity不能销毁,形成了内存泄漏。

LeakCanary

LeakCanary是Square公司出品的自动监控内存泄漏的library。在Android中使用非常方便,两步操作。

build.gradle添加Gradle依赖,可以指定在debug时才监控,release版本不监控

dependencies {
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3'
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3'
}


Application中调用install即可。

public class MyApplication extends Application {
@Override public void onCreate() {
super.onCreate();
LeakCanary.install(this);
}
}


经过上述两个步骤,app已经具有了自动内存监控功能,并且当发生内存泄漏时,可以自动发出通知。

项目测试截图:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  内存泄露