android性能优化之内存泄露分析

今天聊一聊在android开发中内存泄露的那些事。

在开发中经常听人说到内存泄露和内存溢出这两个词语,有些同学可能还不清楚内存泄露和内存溢出本质上到底有啥区别。

简单的描述一下我对内存泄露和内存溢出的理解:

内存泄露:你new了一个对象,java虚拟机为这个对象在java堆中分配了一块内存,然后这个对象你不再使用了,但是这个对象却没有主动或者被动的被释放回收。没有回收的原因可能是其他对象引用着这个对象,当Java虚拟机触发GC时,垃圾收集器检查到这个对象被其他对象引用着就不会回收掉这个对象,这就造成了内存泄露。

内存溢出:当你准备创建一个比较大的对象时而java堆中没有足够大的内存来为这个对象分配空间。这就造成了内存溢出。

偶然的一次内存泄露不会对我们应用造成影响,频繁的内存泄露就会造成内存溢出以至于java虚拟机抛出 OutOfMemoryError错误以至于使我们的APP闪退。

下面我就说一下怎么用AndroidStudio来检查分析我们的程序有没有内存泄露。

以我们的app为例,在app里选择一个课程进行播放听课,然后退出播放界面互道主界面,然后反复进行此操作两次。现在我们停留在主界面,此时在Java堆内存里应该只有主界面这个activity的实例,不应该有播放界面这个activity的实例。因为我们已经退出了播放界面,这个界面应该被GC回收掉。

我们就来看下当前内存里的情况是不是和我们说的一样只有主界面这个activiy这个实例。

首先在Android Monitor下点击Monitor标签,出现下图


android性能优化之内存泄露分析_第1张图片
QQ截图20170106233057.jpg

点击B图标手动触发一下GC,然后点击C图标,此时会生成一个heap文件。因为我们要详细分析内存泄露原因,需要借助于MAT插件来分析,此时生成的.hprof文件并不能直接在MAT中打开,需要转换一下,具体的转换方法请google。

我们用MAT打开刚才生成的.hprof文件 ,按下图做如下操作

android性能优化之内存泄露分析_第2张图片
QQ截图20170104160002.png

我们目前只分析activiy中的内存泄露所以点击QQL图标 输入 select * from instanceof android.app.Activity 点击红色感叹号,结果如图所示

android性能优化之内存泄露分析_第3张图片
QQ截图20170106234904.jpg

我们看到当前内存里有三个MyPlayVideoActivity(也就是我们的播放界面)实例,怎么会有三个实例呢,我明明已经退出这个界面回到主界面了怎么会没有被回收呢。

对因为内存泄露了所以没有回收。

我们来看下为什么会没有被回收呢,右击MyPlayVideoActity如图操作


android性能优化之内存泄露分析_第4张图片
QQ截图20170106235300.jpg

下图我们具体看下到底谁在引用着MyPlayVideoActivity以至于不能回收

android性能优化之内存泄露分析_第5张图片
QQ截图20170106235942.jpg

从图中我们看到是一个内部类TimerTask在搞鬼,他们的GC链为Timer→MediaController→BaseSharkPlayVdieoActivity

我们知道了是因为这个Timer内部类一直持有MyPlayVideoActivity的引用以至于MyPlayVideoActivity不能被回收从而造成了内存泄露。

既然找到了原因解决掉这个内部类不让它在持有MyPlayVideoActivity的引用,自然就不会出现内存泄露的原因了。

推荐一个工具leakcanary能很好的定位内存泄露,如果你想详细的分析内存泄露还是使用强大的MAT来分析。

你可能感兴趣的:(android性能优化之内存泄露分析)