Android中Memory Leak原因分析及解决办法

在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主要取决于对当前对问题的理解,这需要我们对问题的的建模思想。

(0)

相关推荐

  • Android编程之内存溢出解决方案(OOM)实例总结

    本文实例总结了Android编程之内存溢出解决方案(OOM).分享给大家供大家参考,具体如下: 在最近做的工程中发现加载的图片太多或图片过大时经常出现OOM问题,找网上资料也提供了很多方法,但自己感觉有点乱,特此,今天在不同型号的三款安卓手机上做了测试,因为有效果也有结果,今天小马就做个详细的总结,以供朋友们共同交流学习,也供自己以后在解决OOM问题上有所提高,提前讲下,片幅有点长,涉及的东西太多,大家耐心看,肯定有收获的,里面的很多东西小马也是学习参考网络资料使用的,先来简单讲下下: 一般我们

  • Android编程内存溢出与防范方法浅析

    本文实例讲述了Android编程内存溢出与防范方法.分享给大家供大家参考,具体如下: Android的虚拟机是基于寄存器的Dalvik,它的最大堆大小一般是16M.但是Android采用的是Java语言编写,所以在很大程度上,Android的内存机制等同于Java的内存机制,在刚开始开发的时候,内存的限制问题会给我们带来内存溢出等严重问题.在我们不使用一些内存的时候,我们要尽量在Android或者其他平台上避免在运行其他程序时,保存必要的状态,使得一些死进程所带来的内存问题,应该尽量在关闭程序或

  • android 解决ViewPager加载大量图片内存溢出问题

    1.大家都知道为ViewPager构建适配器继承PagerAdapter,怎么构建就不说了.Viewpager会默认加载当前页和当前页的左右两页.一开始当前页是下标0,所以一开始默认加载第0页(指下标,下同)和第1页.当你向右滑动,当前页为第1页时,ViewPager会加载第2页,这时一共有3页存在(第0,1,2页).再向右滑动,当前页为第2页时,会移除第0页,加载第3页,同理向左滑动当前页为第1页时,会移除第3页.这么说应该懂了吧. 知道了上面的原理,就可以让ViewPager始终只加载3页的

  • Android 内存溢出和内存泄漏的问题

    Android 内存溢出和内存泄漏的问题 在面试中,经常有面试官会问"你知道什么是内存溢出?什么是内存泄漏?怎么避免?"通过这篇文章,你可以回答出来了. 内存溢出 (OOM)是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory:比如只申请了一个integer,但给它存了long才能存下的数,那就会出现内存溢出. 内存泄露 (memory leak)是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存

  • Android 异步获取网络图片并处理导致内存溢出问题解决方法

    测试环境为Adnroid 2.1以上. 1.AndroidManifest.xml 权限配置: 添加互联网访问权限: 复制代码 代码如下: <uses-permission android:name="android.permission.INTERNET" /> 2.异步图片类 ImageDownloadTask 复制代码 代码如下: import java.io.ByteArrayOutputStream; import java.io.IOException; imp

  • Android 使用帧动画内存溢出解决方案

    Android 使用帧动画内存溢出解决方案 最近在项目遇到的动画效果不好实现,就让UI切成图,采用帧动画实现效果,但是在使用animation-list时,图片也就11张,每张图片大概560k左右,结果内存溢出,崩溃 了,自己用了三张都崩溃:拿代码说: 1.anin_searh.xml <?xml version="1.0" encoding="utf-8"?> <animation-list xmlns:android="http://

  • Android加载图片内存溢出问题解决方法

    1. 在Android软件开发过程中,图片处理是经常遇到的. 在将图片转换成Bitmap的时候,由于图片的大小不一样,当遇到很大的图片的时候会出现超出内存的问题,为了解决这个问题Android API提供了BitmapFactory.Options这个类. 2. 由于Android对图片使用内存有限制,若是加载几兆的大图片便内存溢出.Bitmap会将图片的所有像素(即长x宽)加载到内存中,如果图片分辨率过大,会直接导致内存OOM,只有在BitmapFactory加载图片时使用BitmapFact

  • Android避免内存溢出(Out of Memory)方法汇总

    避免内存溢出的方法,主要是对以下三个方面对程序进行优化 内存引用 在处理内存引用之前,我们先来复习下什么是强引用.软引用.弱引用.虚引用 强引用:强引用是使用最普遍的引用.如果一个对象具有强引用,那垃圾回收器绝不会回收它. 当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题. 软引用:如果一个对象只具有软引用,但内存空间足够时,垃圾回收器就不会回收它:直到虚拟机报告内存不够时才会回收, 只要垃圾回收器没

  • android内存及内存溢出分析详解

    一.Android的内存机制    Android的程序由Java语言编写,所以Android的内存管理与Java的内存管理相似.程序员通过new为对象分配内存,所有对象在java堆内分配空间:然而对象的释放是由垃圾回收器来完成的.C/C++中的内存机制是"谁污染,谁治理",java的就比较人性化了,给我们请了一个专门的清洁工(GC).    那么GC怎么能够确认某一个对象是不是已经被废弃了呢?Java采用了有向图的原理.Java将引用关系考虑为图的有向边,有向边从引用者指向引用对象.

  • Android中Memory Leak原因分析及解决办法

    在Android开发过程中,我们经常碰到的情况就是在我们不清楚为什么情况下,程序突然出现Crash了.其中有一类日志相信大家都经常碰到过,这类日志就是OOM相关的日志.这类日志除了我们知道的Bitmap操作的时候会经常导致,还有一种隐藏的较深的原因就是内存泄露(Memory Leak). 内存泄露产生原因和影响: 原因:当一个Object不再需要的时候,本该被GC回收时,但是因为另一个正在使用的Object持有它导致不能正常的被回收,本该被回收的对象不能回收,还存留在堆内存中,此时就产生了内存泄

  • Android实现类似IOS右滑返回的效果(原因分析及解决办法)

    使用类库SwipeBackLayout https://github.com/Issacw0ng/SwipeBackLayout 出现的问题: 1. 主Activity返回时黑屏或者返回只是看到桌面背景而没有看到上一个Activity界面 原因: 使用滑动返回需要在Activity的额主题中声明android:windowIsTranslucent=true,而该属性是设置Activity为是否为透明主题,当主Activity采用透明主题时,由于是app Activity栈中的第一个,所以滑动返

  • 后端接收不到AngularJs中$http.post发送的数据原因分析及解决办法

    1.问题: 后端接收不到AngularJs中$http.post发送的数据,总是显示为null 示例代码: $http.post(/admin/KeyValue/GetListByPage, { pageindex: 1, pagesize: 8 }) .success(function(){ alert("Mr靖"); }); 代码没有错,但是在后台却接收不到数据,这是为什么呢? 用火狐监控:参数是JSON格式 用谷歌监控:传参方式是request payload 可以发现传参方式是

  • PHP中ID设置自增后不连续的原因分析及解决办法

    PHP中ID设置自增后不连续的原因分析如下所述: alter table tablename drop column id; alter table tablename add id mediumint(8) not null primary key auto_increment first; 每次删除把这两行家伙加上就行了 还有就是这个 使用mysqli对象中的query()方法每次调用只能执行一条SQL命令. 如果需要一次执行多条SQL命令,就必须使用mysqli对象中的 multi_que

  • JavaScript中的ParseInt("08")和“09”返回0的原因分析及解决办法

    今天在程序中出现一个bugger ,调试了好久,最后才发现,原来是这个问题. 做了一个实验: alert(parseInt("01")),当这个里面的值为01====>07时都是正常的,但是在"08","09"就会返回0 (这种现象出现在ie内核的浏览器中,如360浏览器就会出现这种错误)(谷歌,火狐不受影响) . 查阅资料得知着这种现象原因: 大神的解释: 01--07自然没有问题,但是09,08都是不合格的八进制形式,所以被按照0处理了

  • 关于获取DIV内部内容报错的原因分析及解决办法

    1.错误描述 2.错误原因 由于向div中添加元素,利用append(); $("#divStyle").append("<div><label>_data[i].name</label></div>"); append里面是动态数据,当请求数据为空时,获取并判断div中的内容: var divContent = $("#divStyle").html(); if(divContent == nul

  • JQuery Dialog对话框 不能通过Esc关闭的原因分析及解决办法

    背景:想通过Esc键关闭展示中的Dialog对话框,发现有些对话框可以,有些会失效. 原因分析: 1.对话框上可以输入内容的标签元素可以,反之不行. 2.如果鼠标点击对话框后,也可以Esc键关闭. 可以看出对话框上是需要聚焦就可以了. 解决方案: 方案一: focus:function(){ $("#id").focus(); } 方案二: 延迟聚焦 setTimeout(function() { $("#id").focus(); }, 500); 以上所述是小编

  • 导致MyEclipse内存不足的原因分析及解决办法

    1.修改eclipse.ini 在Myeclipse安装目录下G:\MyEclipse8.5\Genuitec\MyEclipse 8.5有一个myeclipse.ini配置文件,设置如下: -vmargs -Xmx512m -XX:MaxPermSize=256m -XX:ReservedCodeCacheSize=64m 2.设置Default VM Arguments 在myEclipse中,打开Windows-> Preferences->Java->Installed JREs

  • C#解析json字符串总是多出双引号的原因分析及解决办法

    json好久没用了,今天在用到json的时候,发现对字符串做解析的时候总是多出双引号. 代码如下: string jsonText = "{'name':'test','phone':'18888888888'}"; JObject jo = (JObject)JsonConvert.DeserializeObject(jsonText); string zone = jo["name"].ToString(); string zone_en = jo["

  • php resizeimage 部分jpg文件 生成缩略图失败的原因分析及解决办法

    今天遇到GD的resizeimage 函数处理jpg后缀文件的缩略图的时候 提示该图片不是合法的jpg图片并报错 <b>Warning</b>: imagecreatefromjpeg(): gd-jpeg, libjpeg: recoverable error: Invalid SOS parameters for sequential JPEG 国内网上查了很多资料也没找到有效的解决办法,原来只要把 GD的jpeg文件支持打开即可解决 ini_set('gd.jpeg_igno

随机推荐