OOM的一些理解与处理

来源:互联网 发布:c语言 libevent 编辑:程序博客网 时间:2024/04/30 06:02

这两天听说了很多关于OOM的问题,自己也看了看一些大神的见解与描述,关于OOM的原因和几点建议和Android OOM产生原因及如何解决(自己是菜逼有些看不懂),自己总结了一下。

OOM产生原因

Dalvik VM主要管理的内存 Java heap,由于手机设备的限制,一般一个应用使用的内存不能超过默认值 32M(不同设备略有差异,加上手机更新换代较快,现在128M的也有,可以通过adb shell getprop | grep dalvik.vm.heapgrowthlimit命令查看),一个应用进程的内存可以由2个部门组成:java 使用内存 ,使用内存 这也就是说,当在DVM上申请的堆内存大于默认阀值的时候,我们的应用就会抛出OutOfMemoryError 。一旦内存分配给Java后,以后这块内存纵然开释后,也只能给Java的使用,这个估计跟java虚拟机里把内存分成好几块进行缓存的原因有关,反正C就别想用到这块的内存了,所以要是Java突然占用了一个大块内存,纵然很快开释了,C能使用的内存 = 32M - Java某一瞬间占在的最大内存。 而Bitmap的生成是路程经过过程malloc进行内存分配的,占用的是C的内存。也就是说当Java占的内存多了,Bitmap所能占的内存就少了。

如何解决和避免OOM

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

加载多图:

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

关于软引用的说明: 
软引用(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、解决内存泄露问题

内存泄漏主要是指进程没有及时释放掉没有用的对象,如上面提到的Bitmap没有Recycler()或者Handler对象没有清空等,当进程死掉后仍占着内存,累计多了会造成内存溢出,也就是OOM了(以上是自己的总结,有错请告诉我,与下文无关)。解决该问题主要需要对Android系统各部分组件进行一些较深入了解,比如: 对Activity的生命周期进行了解以后,就应该避免对生命周期之外的引用(其实可以在OnDestroy()方法中释放没用的内存,这也是自己的总结,嘻嘻)。一个应用可能有多个Activity构成,这时候应该考虑使用Application类。(该问题主要是针对Activity中静态对象的控制) 尽量不要由于各种复杂的引用导致GC不能及时的甚至永远不能回收某块内存。

 

 

0 0