Android的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泄露
3.内存压力过大
3-1,图片资源加载过多,超过内存使用空间,例如Bitmap 的使用
3-2,重复创建view,listview应该使用convertview和viewholder
下面针对上面的几个原因说一下避免措施
如何避免oom?
一共三点:
1.避免对象的内存泄露
2.减小对象的内存占用
3.内存对象的重复利用
1.避免对象的内存泄露
内存对象的泄漏,会导致一些不再使用的对象无法及时释放,这样一方面占用了宝贵的内存空间,很容易导致后续需要分配内存的时候,空闲空间不足而出现OOM。显然,这还使得每级Generation的内存区域可用空间变小,gc就会更容易被触发,容易出现内存抖动,从而引起性能问题。
通常来说,Activity的泄漏是内存泄漏里面最严重的问题,它占用的内存多,影响面广,我们需要特别注意以下几种种情况导致的Activity泄漏,service内存泄露和其他内存泄露:
1) 内部类引用导致Activity的泄漏
最典型的场景是Handler导致的Activity泄漏,如果Handler中有延迟的任务或者是等待执行的任务队列过长,都有可能因为Handler继续执行而导致Activity发生泄漏。此时的引用关系链是Looper -> MessageQueue -> Message -> Handler -> Activity。为了解决这个问题,可以在UI退出之前,执行remove Handler消息队列中的消息与runnable对象。或者是使用Static + WeakReference的方式来达到断开Handler与Activity之间存在引用关系的目的。
Activity Context被传递到其他实例中,这可能导致自身被引用而发生泄漏。
内部类引起的泄漏不仅仅会发生在Activity上,其他任何内部类出现的地方,都需要特别留意!我们可以考虑尽量使用static类型的内部类,同时使用WeakReference的机制来避免因为互相引用而出现的泄露。
2)考虑使用Application Context而不是Activity Context
对于大部分非必须使用Activity Context的情况(Dialog的Context就必须是Activity Context),我们都可以考虑使用Application Context而不是Activity的Context,这样可以避免不经意的Activity泄露。、
3)Service引起的内存泄露
典型的是Service忘记关闭,为了避免可以使用IntentService:会自动开一个线程,使用完关闭service
4)BroadCastReceiver引起的泄露
概括一下,避免Context相关的内存泄露,记住以下事情:
比如onReceive方法里执行了太多的操作
5)注意临时Bitmap对象的及时回收
虽然在大多数情况下,我们会对Bitmap增加缓存机制,但是在某些时候,部分Bitmap是需要及时回收的。例如临时创建的某个相对比较大的bitmap对象,在经过变换得到新的bitmap对象之后,应该尽快回收原始的bitmap,这样能够更快释放原始bitmap所占用的空间。
6)注意单例引起的内存泄露
很多内存泄露是由于单例引起的,因为单例