腾讯大神教你如何解决android内存泄露

标签: 腾讯 大神 android | 发表时间:2017-09-25 17:59 | 作者:
出处:https://mp.weixin.qq.com

 经过长期迭代、app出现了占用内存过高的问题,上半年抽时间做了次内存泄露的分析和处理,把app占用内存从70多M降低到30多M,这里做下总结。





效果





修复前





修复后





分析



这里主要是针对业务实际代码进行一下分析和处理,下面会总结实际使用到的一些知识。





什么是内存泄露?





1. java中的内存分配



1.静态存储区:编译时就分配好,在程序整个运行期间都存在,它主要用于存放静态数据和常量;



2.栈区:当方法执行时,会在栈区内存中创建方法内部的局部变量,方法结束后自动释放内存;



3.堆区:通常存放new出来的对象。由java垃圾会收器进行回收。内存泄露一般是指堆内存的泄露。



2.如何识别对象无引用?



1.引用计数法:直接计数,简单高效,Python便是采用该方法。但是如果出现两个对象互相引用,即时它们都无法被外界访问到,计数器不为0,它们也得不到回收。



为了解决这种问题,java采用的是第二种方法。



2.可达性分析法,这个方法设置了一系列的“GC Roots”对象作为索引七点,如果一个对象与起点对象之间均无可达路径,那么这个不可达的对象就会成为回收对象。



这种方法处理两个对象相互引用的问题,如果两个对象均没有外部引用,那么就会被判断为不可达对象进而被回收。



这边可以被当做GC roots的对象主要有以下:



android给出的解析



参考https://developer.android.com/studio/profile/am-memory.html?utm_source=android-studio



java给出的解析



参考http://help.eclipse.org/luna/index.jsp?topic=%2Forg.eclipse.mat.ui.help%2Fconcepts%2Fgcroots.html&cp=37_2_3



Garbage Collection Roots



A garbage collection root is an object that is accessible from outside the heap. The following reasons make an object a GC root:



1.System Class



Class loaded by bootstrap/system class loader. For example, everything from the rt.jar like java.util.* .



2.JNI Local

Local variable in native code, such as user defined JNI code or JVM internal code.



3.JNI Global

Global variable in native code, such as user defined JNI code or JVM internal code.



4.Thread Block

Object referred to from a currently active thread block.



5.Thread

A started, but not stopped, thread.



6.Busy Monitor

Everything that has called wait() or notify() or that is synchronized. For example, by calling synchronized(Object) or by entering a synchronized method. Static method means class, non-static method means object.



7.Java Local

Local variable. For example, input parameters or locally created objects of methods that are still in the stack of a thread.



8.Native Stack

In or out parameters in native code, such as user defined JNI code or JVM internal code. This is often the case as many methods have native parts and the objects handled as method parameters become GC roots. For example, parameters used for file/network I/O methods or reflection.



9.Finalizable

An object which is in a queue awaiting its finalizer to be run.



9.Unfinalized

An object which has a finalize method, but has not been finalized and is not yet on the finalizer queue.



9.Unreachable

An object which is unreachable from any other root, but has been marked as a root by MAT to retain objects which otherwise would not be included in the analysis.



10.Java Stack Frame

A Java stack frame, holding local variables. Only generated when the dump is parsed with the preference set to treat Java stack frames as objects.



11.Unknown



An object of unknown root type. Some dumps, such as IBM Portable Heap Dump files, do not have root information. For these dumps the MAT parser marks objects which are have no inbound references or are unreachable from any other root as roots of this type. This ensures that MAT retains all the objects in the dump.



总结下:当前运行线程持有的对象;已经开启但是没有终止运行的线程;方法运行时的引用参数(被栈引用的堆对象);native方法中引用的对象;静态变量和方法;bootstrap loader加载的class对象;



3.内存泄漏



对于保持着引用,但是逻辑上不会再用到的对象,垃圾回收器是不会进行回收的。这些对象会累积在内存中,直到程序结束。这就是所谓的内存泄露。







如何发现内存泄漏







传统手工方法:



反复操作应用,观测内存变化,gc后内存是否有回落到原先的值;比较粗略,难发现问题。



通过代码检测:



  • 在程序中启动长期工作的后台线程LeakThread进行内存检测

  • 向application注册页面生命周期的监听

  • 在监听类中对 onActivityDestoryed(Activity activity) 的事件回调做处理:在activity被调用onDestroy的时候,创建该activity的weak reference对象ref

  • LeakThread每隔段时间就去检测该ref.get()是否为空,如果为空则说明正常释放,不为空就手动触发gc,再隔断时间去查看是否已被回收。如果没有就dump heap,进而分析并计算到gc roots的最短路径,判断是否有泄露,如果有,就通知出来。

  • 已经有实现的开源检测工具LeakCanary:https://github.com/square/leakcanary 强烈推荐!目前我们项目已经集成并使用了。



  • 参考:http://km.oa.com/group/15137/articles/show/295872?kmref=search&from_page=2&no=7





如何定位内存泄漏





1.如何导出.prof文件?



如何取得内存快照,生成prof文件





2.如何分析.prof文件?



studio自带的内存泄露分析工具





导出该prof文件,生成MAT可分析的格式。

使用指令:hprof-conv input.hprof output.hprof



  • ABLEOU-MC4:~ ableou$ cd /Users/ableou/Downloads/adt-bundle-mac-x86_64-20140321\ 2/sdk/tools/



  • ABLEOU-MC4:tools ableou$ hprof-conv /Users/ableou/work/AS_ZhongCai500/captures/com.zhongcai500_2017.06.29_15.24.hprof /Users/ableou/work/AS_ZhongCai500/captures/com.zhongcai500_out_2.hprof



接下来,对转换后的prof文件,使用MTA分析



3.使用MAT进行分析



  • 参考网站:http://androidperformance.com/2015/04/11/AndroidMemory-Usage-Of-MAT.html





常见泄露举例







1.CONTEXT_LEAK



持有activity对象不释放



  • 让在整个程序运行过程中不会消亡的对象(如 单例对象)持有activity,可以参看initActivity之前的代码

  • 非静态内部类持有外部类对象,并做耗时操作

  • 延时处理的handler中持有的对象



解决:



  • 1.单例对象尽量使用applicationContext

  • 2.如果必须在单例对象中使用activity,则定义接口,让activity实现该接口,并通过接口使用,在activity destroy的时候需要主动触发回收。

  • 3.修改为持有弱引用

  • 4.在activity onDestroy之前把不需要处理的回调进行关闭。





2.RESOURCE_LEAK



我们代码主要存在:输入输出流没关闭







还有cursor没关闭、注册监听没有反注册等等。





如果想看更多可以参考:



  • http://km.oa.com/group/20528/articles/show/186773?kmref=search&from_page=1&no=10



  • https://zhuanlan.zhihu.com/p/25213586



小结:知道了泄露的原理和发现泄露的方法之后,解决泄露就不成为一个问题了。



END







相关 [腾讯 大神 android] 推荐:

腾讯大神教你如何解决android内存泄露

- -
 经过长期迭代、app出现了占用内存过高的问题,上半年抽时间做了次内存泄露的分析和处理,把app占用内存从70多M降低到30多M,这里做下总结. 这里主要是针对业务实际代码进行一下分析和处理,下面会总结实际使用到的一些知识. 1.静态存储区:编译时就分配好,在程序整个运行期间都存在,它主要用于存放静态数据和常量;.

腾讯也来 Android 应用助手,现在你用哪家的?

- 高春辉 - Engadget 中国版
引用来源 | 此文章网址 | 转寄此文章 | 回应.

【腾讯Bugly干货分享】Android减包 - 减少APK大小

- - CSDN博客移动开发推荐文章
本文是对Google官方文档 Reduce APK Size 的翻译,点击“阅读原文”可以查看英文原文. 译者简介:damonxia(夏正冬),天天P图Android工程师. 用户经常会避免下载看起来体积较大的应用,特别是在不稳定的2G、3G网络或者在以字节付费的网络. 这篇文章描述了怎样减少你的APK大小,这会让更多的用户愿意下载你的应用.

腾讯高级设计师谈微信Android版本改版 Android Design是大势所趋

- - 互联网的那点事
编者按:本篇投稿选自 腾讯大讲堂(更多腾讯产品技术文章,可以关注“腾讯大讲堂”微信公众账号),由腾讯研发管理部高级设计师Vertu撰写,他以产品设计师的视角,对比解读了微信的旧容与新妆,也讲了Android版微信5.2放弃iOS UI设计背后的故事. 1 月 21 日,新的 Android 版微信在应用宝上线内测,很多用户第一时间更新了.

腾讯应用中心Android客户端上线 设安全认证

- Tony - cnBeta.COM
Android腾讯应用中心客户端昨日全新上线,其前身是“QQ手机软件管理”. 腾讯应用中心Android客户端全新的UI和架构,显示出腾讯应用中心的社区化和开放平台理念,同时腾讯应用中心每款应用都经专业的QQ手机管家认证,用户下载更安心.

Android分享到腾讯微薄,信息,新浪微薄,的实现方式

- - 博客园_首页
android:text="分享" /> . Intent intent = new Intent(Intent.ACTION_SEND); //启动分享发送的属性. intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//这个也许是分享列表的背景吧.

android客户端接入新浪、腾讯微博以及人人网

- - CSDN博客移动开发推荐文章
本文原创 http://blog.csdn.net/yanbin1079415046,转载请注明出处.   从事android工作也有段时间了,碍于肚子里料不多,一直也没写过什么东西. 最近刚好项目中要接入新浪微博,就顺便研究了一下android客户端接入腾讯微博和人人网. 由于是第一次写东西,加上本人小菜鸟一个,请高手勿喷,觉得文章没用的飘过,当然啦,觉得还有点用的就看看吧.

【腾讯Bugly干货分享】WebP原理和Android支持现状介绍

- - IT瘾-geek
目前网络中图片仍然是占用流量较大的一部分,对于移动端更是如此,因此,如何在保证图片视觉不失真前提下缩小体积,对于节省带宽和电池电量十分重要. 然而目前对于JPEG、PNG、GIF等常用图片格式的优化已几乎达到极致,因此Google于2010年提出了一种新的图片压缩格式 — WebP,给图片的优化提供了新的可能.

在Android手机上使用腾讯的ncnn实现图像分类 - 夜雨飘零 - CSDN博客

- -
在之前笔者有介绍过《在Android设备上使用PaddleMobile实现图像分类》,使用的框架是百度开源的PaddleMobile. 在本章中,笔者将会介绍使用腾讯的开源手机深度学习框架ncnn来实现在Android手机实现图像分类,这个框架开源时间比较长,相对稳定很多. ncnn的GitHub地址:https://github.com/Tencent/ncnn.

腾讯的内涵图

- keeno - 阿禅日记
2011年5月31日10:33,腾讯QQ 浏览器首页的截图如下:. 内涵关键词:释放、aiww、64. 1小时后,腾讯将图片替换掉了. 对这位如此有内涵的经理或编辑或设计师致敬. © Jason Ng for 阿禅日记, |. 不要用中国手机号来找回Gmail密码.