Android 内存溢出处理方案
转自 : http://www.cnblogs.com/hello-ruby/archive/2013/04/19/3031098.html
首先我们来看看android内存溢出的原因,有可能是:
- 由于我们程序的失误,长期保持某些资源(如Context)的引用,造成内存泄露,资源造成得不到释放。
- 保存了多个耗用内存过大的对象(如Bitmap),造成内存超出限制。
一旦出现了内存溢出,一般情况下从以下几个方面入手:
- 从内存引用上做处理,常用的有软引用,强化引用,弱引用。
- 在内存中加载图片时直接在内存中作处理,比如边界压缩。。。
- 动态回收内存
- 优化虚拟机堆内存分配
- 自定义堆内存大小
解决方案:
a. 强引用、软引用等的介绍
heap中对象有强可及对象、软可及对象、弱可及对象、虚可及对象和不可到达对象。应用的强弱顺序是强、软、弱、和虚。对于对象是属于哪种可及的对象,由他的最强的引用决定
强引用:只要存在对heap中对象的引用,gc就不会收集该对象.
软引用:软引用是主要用于内存敏感的高速缓存。在jvm报告内存不足之前会清除所有的软引用,这样以来gc就有可能收集软可及的对象,可能解决内存吃紧问题,避免内存溢出。什么时候会被收集取决于gc的算法和gc运行时可用内存的大小。当gc决定要收集软引用是执行以下过程
弱引用:当gc碰到弱可及对象,并释放abcWeakRef的引用,收集该对象。但是gc可能需要对此运用才能找到该弱可及对象。
虚引用:就是没有的意思,建立虚引用之后通过get方法返回结果始终为null,通过源代码你会发现,虚引用通向会把引用的对象写进referent,只是get方法返回结果为null.先看一下和gc交互的过程在说一下他的作用.
b. 图片加载优化
尽量不要使用setImageBitmap或setImageResource或BitmapFactory.decodeResource来设置一张大图,
因为这些函数在完成decode后,最终都是通过java层的createBitmap来完成的,需要消耗更多内存。
因此,改用先通过BitmapFactory.decodeStream方法,创建出一个bitmap,再将其设为ImageView的 source,
decodeStream最大的秘密在于其直接调用JNI>>nativeDecodeAsset()来完成decode,
无需再使用java层的createBitmap,从而节省了java层的空间。
如果在读取时加上图片的Config参数,可以跟有效减少加载的内存,从而跟有效阻止抛out of Memory异常
另外,decodeStream直接拿的图片来读取字节码了, 不会根据机器的各种分辨率来自动适应,
使用了decodeStream之后,需要在hdpi和mdpi,ldpi中配置相应的图片资源,
否则在不同分辨率机器上都是同样大小(像素点数量),显示出来的大小就不对了。
1.
InputStream is = this.getResources().openRawResource(R.drawable.pic1);
BitmapFactory.Options options=new BitmapFactory.Options();
options.inJustDecodeBounds = false;
options.inSampleSize = ; //width,hight设为原来的十分一 ps.慎用会影响图片质量
Bitmap btp =BitmapFactory.decodeStream(is,null,options);
2.
if(!bmp.isRecycle() ){
bmp.recycle() //回收图片所占的内存
system.gc() //提醒系统及时回收
}
//奉上一个方法
/**
* 以最省内存的方式读取本地资源的图片
* @param context
* @param resId
* @return
*/
public static Bitmap readBitMap(Context context, int resId){
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inPreferredConfig = Bitmap.Config.RGB_565;
opt.inPurgeable = true;
opt.inInputShareable = true;
//获取资源图片
InputStream is = context.getResources().openRawResource(resId);
return BitmapFactory.decodeStream(is,null,opt);
}
c. 优化Dalvik虚拟机的堆内存分配
对于Android平台来说,其托管层使用的Dalvik JavaVM从目前的表现来看还有很多地方可以优化处理,
比如我们在开发一些大型游戏或耗资源的应用中可能考虑手动干涉GC处理,
使用 dalvik.system.VMRuntime类提供的setTargetHeapUtilization?方法可以增强程序堆内存的处理效率。
当然具体原理我们可以参考开源工程,这里我们仅说下使用方法: 代码如下:
private final static floatTARGET_HEAP_UTILIZATION = 0.75f;
在程序onCreate时就可以调用
VMRuntime.getRuntime().setTargetHeapUtilization?(TARGET_HEAP_UTILIZATION)
d. 自定义堆内存大小
private final static int CWJ_HEAP_SIZE = 6* 1024* 1024 ;//设置最小heap内存为6MB大小
VMRuntime.getRuntime().setMinimumHeapSize(CWJ_HEAP_SIZE);
这个方法是强制性的
总结一下:
要避免内存泄露,主要要遵循以下几点:
第一:不要为Context长期保存引用(要引用Context就要使得引用对象和它本身的生命周期保持一致)。
第二:如果要使用到Context,尽量使用ApplicationContext去代替Context,因为ApplicationContext的生命周期较长,引用情况下不会造成内存泄露问题
第三:在你不控制对象的生命周期的情况下避免在你的Activity中使用static变量。尽量使用WeakReference去代替一个static。
第四:垃圾回收器并不保证能准确回收内存,这样在使用自己需要的内容时,主要生命周期和及时释放掉不需要的对象。尽量在Activity的生命周期结束时,在onDestroy中把我们做引用的其他对象做释放,比如:cursor.close(),bitmapObject.recycle()。
Android 内存溢出处理方案的更多相关文章
- 【转载】Android 内存溢出如何发生的。
[转载]Android 内存溢出如何发生的. 且谈Android内存溢出 前言 关于android的内存溢出在创新文档库中也有不少,网络上也有很多这方面的资料.所以这遍文章不算是正真意义上的创新,仅仅 ...
- Android内存溢出解决方案(OOM)
众所周知,每个Android应用程序在运行时都有一定的内存限制,限制大小一般为16MB或24MB(视平台而定).因此在开发应用时需要特别关注自身的内存使用量,而一般最耗内存量的资源,一般是图片.音频文 ...
- Android 内存溢出管理与测试
今天发现正在做的项目,时不时的会报错:dalvikvm heap out of memory on a 7458832-byte allocation (堆分配的内存溢出) 为什么会内存溢出呢?我以前 ...
- Android内存溢出、内存泄漏常见案例及最佳实践总结
内存溢出是Android开发中一个老大难的问题,相关的知识点比较繁杂,绝大部分的开发者都零零星星知道一些,但难以全面.本篇文档会尽量从广度和深度两个方面进行整理,帮助大家梳理这方面的知识点(基于Jav ...
- Android 内存溢出解决方案(OOM) 整理总结
在最近做的工程中发现加载的图片太多或图片过大时经常出现OOM问题,找网上资料也提供了很多方法,但自己感觉有点乱,特此,今天在不同型号的三款安卓手机上做了测试,因为有效果也有结果,今天小马就做个详细的总 ...
- android 内存溢出问题分析
最近的项目中,内存一直再增长,但是不知道是什么问题,导致内存溢出,在网上看到了这么一篇关于内存分析与管理的文章,解决了部分问题,感觉这篇文 章还不错,就转帖到我的blog上了,希望对大家有所帮助. ...
- Android 内存溢出解决方案(OOM) 整理总结<转>
在最近做的工程中发现加载的图片太多或图片过大时经常出现OOM问题,找网上资料也提供了很多方法,但自己感觉有点乱,特此,今天在不同型号的三款安卓手机上做了测试,因为有效果也有结果,今天小马就做个详细的总 ...
- android 内存溢出与内存泄露
内存溢出就是软件运行需要的内存,超出了java虚拟机给他分配的可用的最大内存 内存泄露就是在缓存图片文字等等的时候,没有关闭流所导致的内存泄露
- android 内存溢出oom错误的一些小见解
转:http://blog.csdn.net/xuhui_7810/article/details/9493681 我们在代码里调用setBackgroundResource(int resid)来设 ...
随机推荐
- History(历史)命令用法 15 例
如果你经常使用 Linux 命令行,那么使用 history(历史)命令可以有效地提升你的效率.本文将通过实例的方式向你介绍 history 命令的 15 个用法. 使用 HISTTIMEFORMAT ...
- Win7 丢失MSVCR110.DLL的解决办法
1 从下面的网站下载dll文件 http://www.ddooo.com/softdown/27034.htm 2 把该文件放到C:\Windows\SysWOW64目录下(64位系统)或者C:\ ...
- Linux VPS/server上用Crontab来实现VPS自己主动化
VPS或者server上常常会须要VPS或者server上常常会须要定时备份数据.定时运行重新启动某个服务或定时运行某个程序等等,一般在Linux使用Crontab,Windows以下是用计划任务(W ...
- uva live 4394 String painter 区间dp
// uva live 4394 String painter // // 这一题是训练指南上dp专题的习题,初看之下认为仅仅是稍微复杂了一点 // 就敲阿敲阿敲,两个半小时后,发现例子过了.然而自己 ...
- dm385的分辨率切换
建议用两个RSZ的输出来完成切换分辨率功能,帧率可以通过软件丢帧来实现. 两个SWMS增加了两个1080p60的读和写,对系统影响是比较大的. http://www.deyisupport.com/q ...
- Android Studio集成Genymotion 及Genymotion 配置ADB
1.打开 Android Studio,依次[File]-[Settings],快捷键 Ctrl + Alt + S 2.在打开的 settings 界面里找到 plugins 设置项,点击右侧的“ ...
- WebService_使用三要素
一.Java中WebService规范 JAVA 中共有三种WebService 规范,分别是JAX-WS.JAX-RS.JAXM&SAAJ(废弃). 1.JAX-WS规范 JAX-WS 的全 ...
- Gradle 安装
Gradle介绍 Gradle是一个基于JVM的构建工具,它提供了: 像Ant一样,通用灵活的构建工具 可以切换的,基于约定的构建框架 强大的多工程构建支持 基于Apache Ivy的强大的依赖管理 ...
- (续)linux SD卡初始化---mmc_sd_init_card函数
mmc_sd_init_card剩下的关于UHS-I的分支结构. uhs-I的初始化流程图如图: 红线标出的部分是已经做了的事,与上一篇那个流程图是一致的,之后就是if分支中做的事. if分支中的函数 ...
- YTU 2418: C语言习题 矩阵元素变换
2418: C语言习题 矩阵元素变换 时间限制: 1 Sec 内存限制: 128 MB 提交: 293 解决: 155 题目描述 将一个n×n(2<n<10,n为奇数)的矩阵中最大的元 ...