App运行时发生OOM的原因你知道哪几种?如何避免?
1.资源对象没关闭造成的内存泄露,try catch finally中将资源回收放到finally语句可以有效避免OOM。资源性对象比如:
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
如何避免内存泄露:
1.使用缓存技术,比如LruCache、DiskLruCache、对象重复并且频繁调用可以考虑对象池
2.对于引用生命周期不一样的对象,可以用软引用或弱引用SoftReferner WeakReferner
3.对于资源对象 使用finally 强制关闭
4.内存压力过大就要统一的管理内存
1.资源对象用完没有关闭,造成内存泄漏。避免:对于资源性对象,在try catch finally中将资源对象放在finally中进行回收处理,可以有效避免OOM。资源性对象例如:
1-1:Cursor(使用Curosr.close())
1-2: 没有关闭InputStream/OutputStream
1-3:使用完registerReceiver后没有调用unregisterReceiver
1-4: Bitmap使用完后没有调用recycle
2.作用域不一样,导致对象不能被垃圾回收器回收
2-1:非静态内部类隐式持有外部类的引用
2-2:Context泄漏:
2-2-1:不要保留Context-Activity长时间的引用(使用Context-Activity时必须确保和Activity一样的生命周期)
2-2-2:使用Context-Application代替Context-Activity
2-2-3: 如果你不想控制内部类的生命周期,应该避免在Activity中使用非静态内部类,应该使用静态内部类,并且在其中创建一个Activity的弱引用(WeakRefrener)
2-3:Thread中引用其他对象也容易造成内存泄漏
2-4:OnReceive方法里执行了太多操作
3.内存压力过大
3-1:图片资源加载过多,超出内存使用空间,例如Bitmap
3-2: 重复创建View,listview应该复用convertview和viewholder
避免内存泄漏:
1:使用缓存技术,如LruCache、DisLruCache、对象重复并且频繁调用可以考虑对象池
2:对于生命周期不一样的对象,可以采用软引用或弱引用(SoftRefrener,WeakRefrener)
3: 对于资源对象用完后在finally中强制关闭
4:内存压力过大,就要用统一的内存管理
a) 如果Context对象发生了内存泄露,比如像Activity这样的重量级Context对象引用了大量很占内存的对象,例如View层级以及其他的资源,一旦Context对象发生泄露,那它引用的所有对象都发生泄露,很容易发生OOM
b) 静态Activity,在生命周期结束之前没有被清除引用
c) 静态View,一个view被加入到界面,会持有Context(Activity或者Fragment)的强引用,如果一个静态成员引用了这个view,也即引用了一个Context,在生命周期结束之后若仍然保持引用则导致内存泄露
d) 内部类静态成员引用外部类成员,内部类可以引用外部类成员,是因为持有外部类的引用。同样匿名内部类也会持有定义他们的对象的引用,比如在Activity里定义一个匿名的AsyncTask对象就很有可能发生内存泄露,在Activity销毁之后,AsyncTask还在执行,就会阻止gc,直到执行结束才能回收。
同理,定义一个匿名Runnable对象并提交到Handler,也可能发生Activity泄露,Runnable对象间接地引用了定义它的Activity对象,被提交到Handler的MessageQueue中,如果在Activity销毁之后还没有被处理,则导致泄露
同理还有Thread和TimeTask等,只要是匿名内部类都会持有定义他们的外部类的引用
e) 系统服务,Context对象注册服务之后,服务内部持有Context对象的引用,所以在Context生命周期结束之前没有注销服务的话就会发生内存泄漏
f) Cursor、IO对象没有及时关闭
g) Bitmap使用后没有recycle()
a) 频繁创建对象
b) 图片资源加载过多,例如Bitmap
c) 重复创建View
a) 对于大部分非必须使用Activity Context的情况(Dialog的Context必须是Activity Context),我们可以考虑使用Application Context
b) 及时关闭Cursor对象、IO对象
c) 注意服务或***的注销
d) 使用静态内部类,其中拥有对外部类的WeakReference
a) 使用更加轻量的数据结构,考虑使用ArrayMap/SparseArray而不是HashMap
b) 避免使用Enum,Enums比静态变量占用两倍以上的内存
c) 减小Bitmap对象的内存占用,重采样、压缩、使用合适的格式解码,使用ARGB_8888/RBG_565/ARGB_4444/ALPHA_8,存在很大差异
d) 使用对象池来对进行内存对象的重复利用
e) listview应用用convertView和静态ViewHolder