本文来自于Dev Club 开发者社区,非经做者赞成,请勿转载,原文地址:http://dev.qq.com/topic/57d14047603a5bf1242ad01bphp
内存泄漏问题大约是Android开发者最烦恼的问题之一了,项目中连续遇到几个内存泄漏问题,这里简单总结下检查分析内存泄漏的一些工具与方法。java
你们都知道,java是有垃圾回收机制的,这使得java程序员比C++程序员轻松了许多,存储申请了,不用心心念念要加一句释放,java虚拟机会派出一些回收线程兢兢业业不定时地回收那些再也不被须要的内存空间(注意回收的不是对象自己,而是对象占据的内存空间)。程序员
Q1:什么叫再也不被须要的内存空间?微信
**答:**Java没有指针,全凭引用来和对象进行关联,经过引用来操做对象。若是一个对象没有与任何引用关联,那么这个对象也就不太可能被使用到了,回收器即是把这些“无任何引用的对象”做为目标,回收了它们占据的内存空间。app
Q2:如何分辨为对象无引用?eclipse
**答:**2种方法编辑器
引用计数法 直接计数,简单高效,Python即是采用该方法。可是若是出现 两个对象相互引用,即便它们都没法被外界访问到,计数器不为0它们也始终不会被回收。为了解决该问题,java采用的是b方法。工具
可达性分析法 这个方法设置了一系列的“GC Roots”对象做为索引发点,若是一个对象 与起点对象之间均无可达路径,那么这个不可达的对象就会成为回收对象。这种方法处理 两个对象相互引用的问题,若是两个对象均没有外部引用,会被判断为不可达对象进而被回收(以下图)。测试
Q3:有了回收机制,放心大胆用不会有内存泄漏?线程
**答:**答案固然是No!
虽然垃圾回收器会帮咱们干掉大部分无用的内存空间,可是对于还保持着引用,但逻辑上已经不会再用到的对象,垃圾回收器不会回收它们。这些对象积累在内存中,直到程序结束,就是咱们所说的“内存泄漏”。
固然了,用户对单次的内存泄漏并无什么感知,但当泄漏积累到内存都被消耗完,就会致使卡顿,崩溃。
内存泄漏不可小视,在Android开发中,好比说一个Activity页面会占用许多资源开销,若是页面发生泄漏,关闭之后页面没有能被系统回收,对应用程序的伤害是很大的。
Q1:在Android开发测试中通常如何发现内存泄漏的发生呢?
答:
方法1:反复操做观察内存变化
内存泄漏常见变现为程序使用时间越长,内存占用越多。那咱们经过反复操做应用,好比反复点开/关闭页面,观察内存变化情况是否一点点上涨,能够粗略地判断是否有内存泄漏
1.经过 DDMS 中的 heap 工具,能够查看应用内存的使用状况
2.Android studio也能够方便查看
方法2:经过代码检测Activity泄漏
基本思路:
1)debug版本能够起一个长期工做的线程LeakThread在后台专门作泄漏检测
2)向Application注册一个 页面生命周期 的监听:application.registerActivityLifecycleCallbacks
3)在监听类中对 onActivityDestoryed(Activity activity) 的事件回调作处理:
若是一个Activity走到onDestroy,那么这个Activity对象就是须要被回收的目标。
咱们声明一个检测对象的弱引用ref = new WeakReference<Object>(activity)。
**PS:**与强引用和软引用相比,弱引用不会被回收器当作一个“有效”的引用,不会影响其引用对象的释放。实际上,垃圾回收器会坚决果断地回收只有弱引用的对象~
4)在 LeakThread中咱们每隔一段时间检测一下ref.get() 是否为空,为空说明activity已被释放。不为空能够手动触一次发gc;若是超过一段时间,好比50s,页面对象还未被清理,咱们能够推断内存泄漏的发生.
5)当内存泄漏发生时,提示给开发者,并自动dump出.prof文件。
由于代码检测不是这里的重点,代码就不贴了,只记思路。
发现可能出现内存泄漏时,咱们须要对.prof文件进行分析,方能快速定位到是哪一个倒霉家伙致使了内存泄漏
打开DDMS ,Eclipse 能够切到DDMS视图,Android studio能够从Tools-Android-Android device monitor进入DDMS
找到app的进程,在进程上方点击“update heap”按钮,能够先主动出发一次GC,待内存占用数据稍微稳定下来后 点击“Dump HProf File”,即可以导出.prof文件
Android studio能够直接打开prof文件。点开Analyzer Tasks的面板,点击右上角的开始按钮。
分析完成后,发生内存泄漏的页面对象会出如今Analysis Results面板-Leak Activityes的目录下。
如图,原来泄漏发生是LoadingRoomActivity的锅!
在官网能够下载到它:
虽然MAT不会准确告诉你你的代码哪泄漏了,可是它会给你发现哪泄露的数据和线索。
在MAT中打开.prof页面,你可能会遇到一点小挫折:
如上图,可能会弹出 ‘Parsing heap dump from xxx has encountered a proplem’ 的错误弹窗
这是由于文件版本和编辑器能支持的版本有冲突的缘由。
解决方案以下:
Sdk安装目录下platform-tools里有一个hprof-conv工具能够解决该问题。在cmd控制台执行:
hprof-conv input.hprof output.hprof
从新再MAT打开output.hprof 就能够打开了~
值得一提的是,若是你dump出的文件太大的话,也有可能发现打不开的现象,这时候,打开安装MAT目录下的MemoryAnalyzer.ini 把-XmX改大些重启便可。可是也不要改得比你机器的可用内存还大,不能太贪心哈哈~
经过MAT打开.phrof文件后,会弹出Overview 和 Leak Suspects 2个标签页。
Leak Suspects标签页可见以下图:
Leak Suspects视图展现了app内存占用的比例,浅色是空闲的内存,其余是内存占用的空间。每块内存对应的问题也都列在下面。点开每一个Problem Suspect下的details,能够看到有哪些类的实例占用了内存和占用大小等信息~
此时咱们已经有了怀疑的目标,为了更清晰地查看,咱们能够回到Overview页面,打开Histogram页面:
在打开的Histogram标签页中,咱们填入检测对象,在列出的匹配项中过滤掉对象的非强引用。
到这里咱们就能够看到,是哪一个坏蛋hold住了你的对象了。MAT可以给到的支持也就到这里,接下来,仍是须要你根据这些线索到代码中寻找判别和修正了~``
更多精彩内容欢迎关注腾讯优测的微信公众帐号:
腾讯优测是专业的移动云测试平台,为应用、游戏,H5混合应用的研发团队提供产品质量检测与问题解决服务。不只在线上平台提供「全面兼容测试」、「云手机」等多种质量检测工具,同时在线下为VIP客户配备专家团队,提供定制化综合测试解决方案。真机实验室配备上千款手机,覆盖亿级用户,7*24小时在线运行,为各种测试工具提供支持。