Android 常见 Memory Leak 原因及解决办法总结
待整理:
http://geek.csdn.net/news/detail/50692
背景
在Android开发过程中,我们经常碰到的情况就是在我们不清楚为什么情况下,程序突然出现Crash了。其中有一类日志相信大家都经常碰到过,这类日志就是OOM相关的日志。这类日志除了我们知道的Bitmap操作的时候会经常导致,还有一种隐藏的较深的原因就是内存泄露(Memory Leak)。
内存泄露产生原因和影响:
- 原因:当一个Object不再需要的时候,本该被GC回收时,但是因为另一个正在使用的Object持有它导致不能正常的被回收,本该被回收的对象不能回收,还存留在堆内存中,此时就产生了内存泄露。
- 影响:Android系统能够为每个应用程序分配的内存是有限的,当一个应用程序中产生的内存泄露过多的时候,会难免导致应用程序需要的内存超过限额而导致内存溢出使得应用程序崩溃。
内存泄露的检测方式
推荐使用 LeakCanary 工具来检测应用程序是否存在内存泄露。LeakCanary是由 Square 开源的一款轻量级的第三方内存泄漏检测工具,当检测到程序中产生内存泄漏时,它将以最直观的方式告诉我们哪里产生了内存泄漏和导致谁泄漏了而不能被回收。
如何避免内存泄露
1、合理使用单例模式。
单例的静态特性使得其生命周期和应用的生命周期一样长。
如图,我们先声明一个单例对象:

然后在Activity使用的时候,习惯性的传一个this:

集成了LeakCanary后测试,发现内存泄露了:

解决方案:
一般情况下,改成如下图的写法就可以了,因为单例的生命周期和应用的一样长,这样就防止了内存泄漏。:

总结:单例模式造成泄漏的原因是拥有更长生命周期的对象持有短生命周期对象的强引用。
2、使用资源时注意资源的关闭
一般情况下,容易产生内存泄露的资源主要为:File,Cursor,Stream,Bitmap,BroadcastReceiver等,这些资源在使用时建议及时关闭,否则当这些资源没有及时回收的时候,内存泄露也就产生了。针对这些资源使用,给如下建议:
- BroadcastReceiver 在register之后,需要在适当的时机unregister
- Cursor、Stream、File 这类资源类型的对象往往会使用一些Cache,所以我们在不使用的时候,应该及时关闭,以便Cache被及时回收。如果我们仅仅把它的引用设置为null,而不去关闭他们,往往会造成内存泄露。一般建议是先close()后置为null。
- Bitmap在不使用的时候,调用recycle()方法。目前 Android 2.3版本以后,不需要我们手动去这样做的,这里也就是简单的交代一下。
3、 合理使用Handler避免内存泄露
在我们使用Handler的时候,经常看到编辑器提示我们Handler可能会造成内存泄露,一般在这种情况下,我们可以将Handler独立出来或者使用静态内部类,这样可以避免内存泄露。
这样做的原因是:非静态内部类会潜在的持有它所属的外部类的引用,但是静态内部类是不会的。
4、 合理的使用WeakReference来引用外部类的成员变量
我们可以使用WeakReference来规避好多潜在的内存泄露的问题,但是并不表明WeakReference就是解决内存泄露的金钥匙。是否使用WeakReference主要取决于对当前对问题的理解,这需要我们对问题的的建模思想。
参考文章:
Android 常见 Memory Leak 原因及解决办法总结的更多相关文章
- android 常见内存泄漏原因及解决办法
android常见内存泄漏主要有以下几类: 一.Handler 引起的内存泄漏. 在Android开发中,我们经常会使用Handler来控制主线程UI程序的界面变化,使用非常简单方便,但是稍不注意,很 ...
- 【hadoop】 running beyond virtual memory错误原因及解决办法
问题描述: 在hadoop中运行应用,出现了running beyond virtual memory错误.提示如下: Container [pid=28920,containerID=contain ...
- Python3 Selenium定位不到元素常见原因及解决办法
Python3 Selenium定位不到元素常见原因及解决办法 一.问题描述 在做web应用的自动化测试时,定位元素是必不可少的,这个过程经常会碰到定位不到元素的情况: 报错信息: no such e ...
- Android App 启动页(Splash)黑/白闪屏现象产生原因与解决办法(转)
转载: Android App 启动页(Splash)黑/白闪屏现象产生原因与解决办法 首先感谢博主分享,本文作为学习记录 惊鸿一瞥 微信的启动页,相信大家都不陌生. 不知道大家有没有发现一个现象 ...
- Connection reset by peer的常见原因及解决办法 RST 大文件上传
Connection reset by peer的常见原因及解决办法 Connection reset by peer的常见原因 - 简书 https://www.jianshu.com/p/263e ...
- .Net内存泄露原因及解决办法
.Net内存泄露原因及解决办法 1. 什么是.Net内存泄露 (1).NET 应用程序中的内存 您大概已经知道,.NET 应用程序中要使用多种类型的内存,包括:堆栈.非托管堆和托管堆.这里我们需 ...
- 安卓android WebView Memory Leak WebView内存泄漏
Android WebView Memory Leak WebView内存泄漏 在这次开发过程中,需要用到webview展示一些界面,但是加载的页面如果有很多图片就会发现内存占用暴涨,并且在退出该界面 ...
- installshield制作的安装包卸载时提示重启动的原因以及解决办法
原文:installshield制作的安装包卸载时提示重启动的原因以及解决办法 有时候卸载installshield制作的安装包程序,卸载完会提示是否重启电脑以完成所有卸载,产生这个提示的常见原因有如 ...
- mysql数据库死锁的产生原因及解决办法
这篇文章主要介绍了mysql数据库锁的产生原因及解决办法,需要的朋友可以参考下 数据库和操作系统一样,是一个多用户使用的共享资源.当多个用户并发地存取数据 时,在数据库中就会产生多个事务同时存取同 ...
随机推荐
- Fiddler手机抓包图文教程
上篇Fiddler教程,我们教了大家Fiddler安装配置及如何使用Fiddler进行基本的Http抓包及模拟请求,今天给大家介绍下如何使用Fiddler进行手机抓包. 运行环境为Windows 10 ...
- Spring框架学习之注解配置与AOP思想
上篇我们介绍了Spring中有关高级依赖关系配置的内容,也可以调用任意方法的返回值作为属性注入的值,它解决了Spring配置文件的动态性不足的缺点.而本篇,我们将介绍Spring的又一大核心 ...
- GPIO复位功能说明
根据STM32L0x3参考手册RM0367,每个General-Purpose IO口,有以下寄存器: 1.4个32位的控制寄存器,分别为GPIOx_MODER,GPIOx_OTYPER,GPIOx_ ...
- 异步 HttpContext.Current实现取值的方法(解决异步Application,Session,Cache...等失效的问题)
在一个项目中,为了系统执行效率更快,把一个经常用到的数据库表通过dataset放到Application中,发现在异步实现中每一次都会出现HttpContext.Current为null的异常,后来在 ...
- [转载] NodeJS无所不能:细数十个令人惊讶的NodeJS开源项目
转载自http://www.searchsoa.com.cn/showcontent_79099.htm 在几年的时间里,Node.JS逐渐发展成一个成熟的开发平台,吸引了许多开发者.有许多大型高流量 ...
- [转载] Java中动态加载jar文件和class文件
转载自http://blog.csdn.net/mousebaby808/article/details/31788325 概述 诸如tomcat这样的服务器,在启动的时候会加载应用程序中lib目录下 ...
- 设计模式的征途—9.组合(Composite)模式
树形结构在软件中随处可见,比如操作系统中的目录结构,公司组织结构等等,如何运用面向对象的方式来处理这种树形结构是组合模式需要解决的问题.组合模式通过一种巧妙的设计方案来使得用户可以一致性地处理整个树形 ...
- ORA-01843: 无效的月份
1.插入的日期如果是DateTime类型的,没有影响 2.如果DateTime.ToString()获取的日期,就会报错,例如(@param_datetime = cf.GetServerDateTi ...
- 关于web程序中使用KindEditor向数据库插入带有格式的数据时出现的问题
最近做一个项目,需要对输入的文字在存入数据库之前进行文本格式编辑,于是我用到了KindEditor,当然怎么用在asp.net页面中,这里就不过多叙述了. 主要是遇到在将赋予格式的文本插入数据库时遇到 ...
- Unity与iOS原生代码之间的相互调用
1.Unity调用iOS: 1.1.在Unity C#中: [ DllImport( "__Internal" )] private static extern int _show ...