性能优化(内存泄漏)

来源:互联网 发布:java 初级项目 编辑:程序博客网 时间:2024/06/05 11:41

新年伊始,并不太忙。闲来无事,准备优化一下我们那传了几代人的古老的app。准备先从内存方面开始着手,这方面不会太大的变动,比较好操刀。

一、知识准备:

(1)JVM的内管理机制
(2)内存泄漏的原理以及android内存泄漏易发生的情景
(3)内存分析工具的使用
下面几篇博客很全面了:
内存溢出与内存泄漏
Android 内存泄漏总结
Java内存、Android 内存泄漏
Java gc(垃圾回收机制)小结,以及Android优化建议

下面这哥们的性能优化前四篇介绍了内存检测工具的使用,很不错,循序渐进:
性能优化

二、实战:

掌握了基本原理和Android Studio 自带的Android Monitor Memory工具以及MAT内存检测工具的基本使用后,就可以进行初步的实践了。

工具是Android Studio和MAT(MAT下载地址),首先运行我们的项目,调出Android Monitor 界面,主要观察Memory项:
这里写图片描述

在登录界面我们的内存消耗可以看到是11.73M,下面登录,进入到主界面:

这里写图片描述

内存有小幅增长,这是正常的,下面反复进入退出某一个界面,并点击几次这里写图片描述Intitate GC按钮,进行手动GC:

这里写图片描述

可以看出在此处界面进出前后,内存会有小幅的涨落,这是系统在GC操作,但总体的占内存却不断升高,相较于开始时多了大约3M,可以判断此界面(Activity)发生了内存泄漏。下面点击Dump Java Heap按钮:这里写图片描述 等待一会儿,studio会自动生成一个.hprof文件:
这里写图片描述

点击右边的Analyzer Task 按钮,弹出的界面中勾选Detect Leaked Activity 选项,点击绿色的三角启动按钮:
这里写图片描述

在给出的分析结果中,我们可以初步判断有两个Acticity发生了内存泄漏,然后用MAT对这个文件进行分析,MAT不能直接识别此格式,要先进行一下格式转换。此文件点击最左边的Captures可以找到 :
这里写图片描述

右键点击,选择Export to stanader.hprof导出,记得保存路径。然后打开MAT,点击File->Open Heap Dump打开我们刚刚保存的文件:

这里写图片描述

这里初步展示了可能存在的问题,不过不(zi)太(ji)清(tai)晰(ruo),我们点击上面那类似三炷香的按钮:

这里写图片描述

会显示出一个统计结果,在Class Name下面那行我们可以输入正则表达式查询,在这里我们输入Activity(毕竟我们主要负责的还是activity):

这里写图片描述

可以看到本来已经被干掉的两个activity依然存在实例,并且第一个ShangppinGuanliActivity居然有9个!!天啦噜,这说明每次进入界面创建的activity并没有成功的被销毁,是有什么东西在一直持有它的引用。下面来找出这个源头,右键这个activity -> List objects -> with incoming referencres :

这里写图片描述

继续右键,查看此类的引用链,并排除软/弱/虚 引用:

这里写图片描述

得到如下结果:

这里写图片描述

可以看出这个activit一直被APP中的mList所引用,找出原因就可以去分析代码,然后填坑了。分析过程不表,说说最终原因吧:这个mList就是我们平常在Application中建立的一个列表,持有activity的引用,用来管理Activity,想必大家都应该很熟悉。但我上某任开发者思路清奇的很:

 App.getInstance().addActivity(this.getActivity()); // 添加Activity

他在BaseFragment的onCreateView()中加了这句话,也就是说每创建一个fragment都会添加进一个Activity的引用!但退出Activity只移除了一个,这就尴尬了,其他的实例继续被引用,造成内存泄露。填坑之后来看下效果:

这里写图片描述

这就很开心了。

0 0