简析Android内存泄漏
来源:互联网 发布:花生壳免费域名管理 编辑:程序博客网 时间:2024/05/21 12:50
GC回收机制
Android虚拟机的垃圾回收采用的是根搜索算法。GC会从根节点(GC Roots)开始对heap进行遍历。到最后,部分没有直接或者间接引用到GC Roots的就是需要回收的垃圾,会被GC回收掉。
根搜索算法相比引用计数法很好的解决了循环引用的问题。举个例子,Activity有View的引用,View也有Activity的引用,之前我还尝试去源代码里找Activity何时和View断开连接是大错特错了。当Activity finish掉之后,Activity和View的循环引用已成孤岛,不再引用到GC Roots,无需断开也会被回收掉。
内存泄露
Android内存泄漏指的是进程中某些对象(垃圾对象)已经没有使用价值了,但是它们却可以直接或间接地引用到gc roots导致无法被GC回收。无用的对象占据着内存空间,使得实际可使用内存变小,形象地说法就是内存泄漏了。
场景案例
1、类的静态变量持有大数据对象
静态变量长期维持到大数据对象的引用,阻止垃圾回收。
2、非静态内部类的静态实例
非静态内部类会维持一个到外部类实例的引用,如果非静态内部类的实例是静态的,就会间接长期维持着外部类的引用,阻止被回收掉。
3、资源对象未关闭
资源性对象如Cursor、File、Socket,应该在使用后及时关闭。未在finally中关闭,会导致异常情况下资源对象未被释放的隐患。
4、注册对象未反注册
未反注册会导致观察者列表里维持着对象的引用,阻止垃圾回收。
5、Handler临时性内存泄露
Handler通过发送Message与主线程交互,Message发出之后是存储在MessageQueue中的,有些Message也不是马上就被处理的。在Message中存在一个 target,是Handler的一个引用,如果Message在Queue中存在的时间越长,就会导致Handler无法被回收。如果Handler是非静态的,则会导致Activity或者Service不会被回收。
由于AsyncTask内部也是Handler机制,同样存在内存泄漏的风险。
此种内存泄露,一般是临时性的。
注意事项
1、不要维持到Activity的长久引用,对activity的引用应该和activity本身有相同的生命周期。
2、尽量使用context-application代替context-activity
3、Activity中尽量不要使用非静态内部类,可以使用静态内部类和WeakReference代替。
泄漏检测
这几天一直在Android Studio下寻找类似于MAT的插件和工具,奈何无功而返,还是MAT比较经典吧!
检测一般分为:静态监测和动态监测。
静态检测:一般可以用Android Studio下自带的 Code Analysis 和lint监测。
静态检测主要是检测资源未关闭的情况,Eclipse和Android Studio都可以检测出IO或者Socket未关闭的情况,然后在finally中关闭即可。
动态监测:还是用比较经典的MAT检测吧!开启DDMS(在eclipse中安装插件)如下图:
动态检测主要是依靠MAT这个工具。2011年Google IO有一个主题演讲,非常详细地讲解了内存泄露的检测,包含MAT工具的使用,值得一看。
我在某项目中使用MAT检测,发现一处内存泄漏,分享一下过程。
从首页到商户列表到商户详情再退回首页执行Dump HPROF File,查看MAT中的Histogram,过滤Activity后结果如下:
HistogramHistogram
仍然存在ShopInfoActivity的实例,选中右键点击Merge Shortest Paths to GC Roots,结果如下:
PathPath
可以看到ShopDatabase中维持着ShopInfoActivity的引用,查看源代码如下:
public class ShopDatabase { … private static ShopDatabase instance; public static ShopDatabase getInstance(Context context) { if (instance == null && context != null) { instance = new ShopDatabase(context); } return instance; } protected Context context; … }
很明显,静态变量instance长期持有context的引用,造成内存泄露。
所以动态检测内存泄露的一个简单思路就是随意操作APP,最后返回首页,然后用MAT检测,查看是否存在Activity多于一个或者Activity不正常存在的问题。
- 简析Android内存泄漏
- 【内存泄漏】Android内存泄漏---单例内存泄漏
- 【内存泄漏】Android内存泄漏---Handler
- Android 内存泄漏调试
- Android 内存泄漏调试
- Android 内存泄漏调试
- Android 内存泄漏调试
- Android 内存泄漏调试
- Android内存泄漏简介
- Android 内存泄漏调试
- Android 内存泄漏调试
- Android 避免内存泄漏
- Android 解析内存泄漏
- Android 内存泄漏调试
- Android 解析内存泄漏
- Android 内存泄漏调试
- Android 内存泄漏调试
- Android内存泄漏简介
- 折角效果
- springmvc中@responseBody返回Json格式中文乱码问题
- Storm Caused by: org.apache.thrift7.transport.TTransportException
- Objective-C内存管理之引用计数
- JS日期操作
- 简析Android内存泄漏
- 【第六章】 AOP 之 6.5 AspectJ切入点语法详解 ——跟我学spring3
- 泛微OA系统利用Check框控制字段显示隐藏
- Android 串口读取设备相关知识。。总结比较乱,部分转载(未完)
- iOS 集合的深复制与浅复制
- android 快速开发(三)巧用公共标题栏:避免每次activity都得写标题栏
- rails权限管理—devise+cancan+rolify
- FMDB官方使用文档-GCD的使用-提高性能(翻译)
- 使用Appium测试native程序