7.如何避免OOM异常

1)什么是OOM OOM,全称“Out Of Memory”,翻译成中文就是“内存用完了”,来源于java.lang.OutOfMemoryError。

2)为什么会OOM?

为什么会没有内存了呢?原因不外乎有两点:

1)分配的少了:比如虚拟机本身可使用的内存(一般通过启动时的VM参数指定)太少。

2)应用用的太多,并且用完没释放,浪费了。此时就会造成内存泄露或者内存溢出。

内存泄露:申请使用完的内存没有释放,导致虚拟机不能再次使用该内存,此时这段内存就泄露了,因为申请者不用了,而又不能被虚拟机分配给别人用。

内存溢出:申请的内存超出了JVM能提供的内存大小,此时称之为溢出。

在c/c++里面由于不存在垃圾回收机制,所以一旦我们使用了动态定义数组例如:new等,都需要在使用完毕后执行设置delete,否则处理大数据时会发生内存溢出。

而在Java语言中,由于存在了垃圾自动回收机制,所以,我们一般不用去主动释放不用的对象所占的内存,也就是理论上来说,是不会存在“内存泄露”的。但是,如果编码不当,比如,将某个对象的引用放到了全局的Map中,虽然方法结束了,但是由于垃圾回收器会根据对象的引用情况来回收内存,导致该对象不能被及时的回收。如果该种情况出现次数多了,就会导致内存溢出,比如系统中经常使用的缓存机制。Java中的内存泄露,不同于C++中的忘了delete,往往是逻辑上的原因泄露。

还有,虽然安卓自带了GC机制,但是GC机制只在内存空间紧张的时候才会被触发,也就是系统分配给该应用的内存空间所剩不多的时候,才会回收掉系统认为不会使用的对象和软引用,如果应用突然在短时间内申请了很大的内存空间,而这个空间已经超过了剩余内存,这个时候GC机制来没来得及触发,或者触发后内存仍然不够用,这个时候就会报OOM了。

而造成OOM的情况大致可以归为以下几类:

1.

资源对象没关闭造成的内存泄露,try catch finally中将资源回收放到finally语句可以有效避免OOM。资源性对象比如:
1-1,Cursor
1-2,调用registerReceiver后未调用unregisterReceiver()
1-3,未关闭InputStream/OutputStream
1-4,Bitmap使用后未调用recycle()

2.

作用域不一样,导致对象不能被垃圾回收器回收,比如:
2-1,非静态内部类会隐式地持有外部类的引用,
2-2,Context泄露
概括一下,避免Context相关的内存泄露,记住以下事情:
   1、 不要保留对Context-Activity长时间的引用(对Activity的引用的时候,必须确保拥有和Activity一样的生命周期)
   2、尝试使用Context-Application来替代Context-Activity 3、如果你不想控制内部类的生命周期,应避免在Activity中使用非静态的内部类,而应该使用静态的内部类,并在其中创建一个对Activity的弱引用。
      这种情况的解决办法是使用一个静态的内部类,其中拥有对外部类的WeakReference。
2-3,Thread 引用其他对象也容易出现对象泄露。
2-4,onReceive方法里执行了太多的操作
3.

内存压力过大
  3-1,图片资源加载过多,超过内存使用空间,例如Bitmap 的使用
  3-2,重复创建view,listview应该使用convertview和viewholder

3)处理方法

1.使用缓存技术,比如LruCache、DiskLruCache、对象重复并且频繁调用可以考虑对象池
2.对于引用生命周期不一样的对象,可以用软引用或弱引用SoftReferner WeakReferner

附上一个区分java里的4种引用java的4种引用方式
3.对于资源对象 使用finally 强制关闭
4.内存压力过大就要统一的管理内存

猜你喜欢

转载自blog.csdn.net/cyanchen666/article/details/81100145