Android OOM产生原因及如何解决

尊重原创,转载请注明出处:Lee http://blog.csdn.net/hnulwt/article/details/44900761

OOM产生原因

OOM产生可能的原因是因为 1、加载大图片导致内存溢出 2、大量内存泄露

OOM产生的本质是什么呢?

Dalvik VM主要管理的内存 Java heap,由于手机设备的限制,一般一个应用使用的内存不能超过默认值 32M(不同设备略有差异,通过adb shell getprop | grep dalvik.vm.heapgrowthlimit命令查看),这也就是说,当在DVM上申请的堆内存大于默认阀值的时候,我们的应用就会抛出OutOfMemoryError。

如何解决和避免OOM

1、解决大图片导致内存溢出

加载多图:

(1)使用软引用、弱引用,当堆内存不足的时候,就可以自动的释放这些缓存的Bitmap对象。

这里有一篇:关于Bitmap分配在native heap还是dalvik heap上的说明。

关于软引用的说明:

软引用(SoftReference)是用来设计object-cache的。他在JVM报告内存不足之前会清除所有的软引用,这样以来gc就有可能收集软可及的对象,可能解决内存不足的问题,避免内存溢出。什么时候会被收集取决于gc的算法和gc运行时可用内存的大小。

关于弱应用的说明:看一个例子更容易懂:

String test =new String("aaa");
WeakReference<String> testWeak = new WeakReference<String>(test);
test = null;
System.out.println("before: "+ testWeak.get());
System.gc();
System.out.println("after: "+ testWeak.get()); 

结果:

before: aaa

after: null

如果你希望能随时取得某对象的信息,但又不想影响此对象的垃圾收集,那么你应该用 弱应用(Weak Reference)来记住此对象。

(2)使用过的图并且不再使用,可以调用Bitmap.recycle()加速回收。

if (null != bitmap && !bitmap.isRecycled()) {
    bitmap.recycle();
}  

(3)考虑使用文件缓存。

整个大图都需要加载:

得到bitmap之前先利用BitmapFactory.Options的inSampleSize的值得到压缩图片。

关键代码:

    // 第一次解析将inJustDecodeBounds设置为true,来获取图片大小
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(res, resId, options);
    // 调用上面定义的方法计算inSampleSize值, calculateInSampleSize方法自己写,这里不再赘述
    options.inSampleSize = calculateInSampleSize(options.outWidth, options.outHeight, reqWidth, reqHeight);

    options.inJustDecodeBounds = false;
    Bitmap bmp = BitmapFactory.decodeResource(res, resId, options); 

只加载部分图片

可以考虑在API 10以后引进的BitmapRegionDecoder类,具体使用方式还未研究,源码注释(BitmapRegionDecoder is particularly useful when an original image is large and you only need parts of the image)。

2、解决内存泄露问题

解决该问题主要需要对Android系统各部分组件进行一些较深入了解,比如:

对Activity的生命周期进行了解以后,就应该避免对生命周期之外的引用。一个应用可能有多个Activity构成,这时候应该考虑使用Application类。(该问题主要是针对Activity中静态对象的控制)

尽量不要由于各种复杂的引用导致GC不能及时的甚至永远不能回收某块内存。

以上是我对OOM问题的一些解决方案,如果大家还有其他很好的方式恳请提出来,共同提升。

时间: 2024-08-11 11:25:18

Android OOM产生原因及如何解决的相关文章

Android OOM(Out of memory) 内存泄露基本知识

Android OOM(Out of memory) 内存泄露基本知识 转载至:http://blog.csdn.net/emilychai2010/article/details/12710135 1. 内存泄露 2. Android里的垃圾回收 3. Heap 4. 调试 5. 常见的内存泄露 1.什么是内存泄露(memory leak)? A "memory leak" in your code is when you keep a reference to an object

Android OOM 系列

2016-04-07 OOM手记 最近组里改友盟上的BUG,NullReference——防空,非UI线程访问UI控件?ClassCastException,Dialog在Activity之后dismis/show...各种问题慢慢解决了,因为大多就是业务逻辑的处理有问题.最后就剩下一个OOM的大头,因为大多数异常不是对应的具体的业务代码,都是系统类抛出的,所以统一放在最后解决:设计良好的app通常常驻内存的也就不过5个Activity,也少有Activity会占用很大的内存,因为历史代码的原因

Android OOM的解决方案

尽量不要使用setImageBitmap或setImageResource或BitmapFactory.decodeResource来设置一张大图, 因为这些函数在完成decode后,最终都是通过java层的createBitmap来完成的,需要消耗更多内存. 因此,改用先通过BitmapFactory.decodeStream方法,创建出一个bitmap,再将其设为ImageView的 source, decodeStream最大的秘密在于其直接调用JNI>>nativeDecodeAsse

[转载]关于安装Android Studio的一些问题的解决方法

最近在研究Android编程,在Android Studio安装和使用时遇到了麻烦,从园子里找到了<关于安装Android Studio的一些问题的解决方法>的,很多问题找到了解决办法. 问题1:每次Fetching android sdk component information 这是在检查你的 Android SDK .有人会在这里卡上很长时间,很大的原因就是:网络连接有问题.可以通过配置 hosts(fan*qiang) 的方式来解决. 如果想跳过这一步 对策: 在Android St

Android OOM问题终极解决方案

大家在安卓开发的过程中使用Bitmap,尤其是当程序中包含大量图片的时候或多或少会遇到OOM(Bitmap: Out Of Memory),遇到这个问题是非常痛苦的,在这里给大家分享一下我自己结合网络上寻找的各种方案,以及自己的研究总结出来的解决方案. 首先大家要知道OOM为什么会出现,通过上网查资料明白了是由于使用了 BitmapFactory.decodeFile(filePath) 这个方法导致的,这个方法通过Google提供的sdk看代码是将整个文件直接读取的所以占用资源比较大,所以找到

android studio创建模拟器报错解决 emulator: ERROR: This AVD&#39;s configuration is missing a kernel file!!

android studio创建模拟器报错 emulator: ERROR: This AVD's configuration is missing a kernel file!! 的解决办法 原因有二:1 没有,解决办法通过sdk mangager 下载 2 找不到,解决办法看系统环境变量path(此种情况多数发生在android Studio和EclipseADT同时存在的情况下) 原因是在刚刚安装完毕的androidstudio的sdk目录下没有system-image目录,也许有但没有相

eclipse导入android项目后出现错误的解决方法

eclipse导入android项目后出现错误的解决方法 出现这样的错误是因为没有为项目指定sdk的原因 为项目指定sdk的方法右键点击工程名称,弹出菜单中点击“Properties->Android”,在Project build target 中指定你要使用的SDK版本即可

android.os.BadParcelableException: ClassNotFoundException when unmarshalling:解决办法

例如在用AlarmManager的时候 1 AlarmManager alarmMgr = (AlarmManager) mContext 2 .getSystemService(Context.ALARM_SERVICE); 3 Intent intent = new Intent(ALARM_ALERT); 4 // intent.setExtrasClassLoader(DBTask.class.getClassLoader()); 5 Bundle mBundle=new Bundle(

android sqlite3程序不存在的解决办法(转)

在android开发中,在使用命令行操作数据库sqlite时,有时候会遇到sqlite3 not found的问题.这是因为你的手机没有安装sqlite3程序.解决办法如下(两种办法结合起来解释的更清楚!!!): 方法1: sqlite3 not found的解决办法(转) 在Android开发方面,我是小白,起步没多久.最近用到了sqlite本地缓存数据,我希望像mysql一样通过命令行查看建立的表以及表中的数据,于是用adb shell进入,敲入sqlite3,提示 sqlite3: not