OOM 内存泄漏

 
 
什么情况导致会导致内存泄漏
1)使用资源时没做关闭处理(cursor,io,bitmap)
2)广播注册后没有反注册
3)Handler发消息(特别是延迟消息),消息没有消费掉,且没有remove。
4)静态变量赋值了生命周期短的对象。比如工具类持有Context对象,设置为某个Activity。
5)单例模式持有activity
6)非静态内部类,持有父类引用,造成父类无法回收
 
解决办法  
1做相应的关闭,
2做相应的反注册,或者反绑定,
3对一直持有的context或activity,尽量用全局一直保活的
 
什么情况下会OOM
相应参考 https://blog.csdn.net/github_37130188/article/details/89609535
什么情况导致内存泄漏?
当一个对象已经不需要再使用本该被回收时,另外一个正在使用的对象持有它的引用从而导致它不能被回收,这导致本该被回收的对象不能被回收而停留在堆内存中,这就产生了内存泄漏
内存泄漏是造成应用程序OOM的主要原因之一。Android系统为每个应用程序分配的内存是有限的,而当一个应用中产生的内存泄漏比较多时,
这就难免会导致应用所需要的内存超过系统分配的内存限额,这就造成了内存溢出从而导致应用Crash。内存泄露原因分析在JAVA中JVM的栈记录了方法的调用,每个线程拥有一个栈。
在线程的运行过程当中,执行到一个新的方法调用,就在栈中增加一个内存单元,即帧(frame)。在frame中,保存有该方法调用的参数、局部变量和返回地址。
然而JAVA中的局部变量只能是基本类型变量(int),或者对象的引用。所以在栈中只存放基本类型变量和对象的引用。引用的对象保存在堆中。当某方法运行结束时,该方法对应的frame将会从栈中删除,
frame中所有局部变量和参数所占有的空间也随之释放。线程回到原方法继续执行,当所有的栈都清空的时候,程序也就随之运行结束。而对于堆内存,堆存放着普通变量。
在JAVA中堆内存不会随着方法的结束而清空,所以在方法中定义了局部变量,在方法结束后变量依然存活在堆中。综上所述,栈(stack)可以自行清除不用的内存空间。但是如果我们不停的创建新对象,
堆(heap)的内存空间就会被消耗尽。所以JAVA引入了垃圾回收(garbage collection,简称GC)去处理堆内存的回收,但如果对象一直被引用无法被回收,造成内存的浪费,无法再被使用。
所以对象无法被GC回收就是造成内存泄露的原因!
OOM 内存泄漏_第1张图片
内存泄露原因
如果持有对象的强引用,垃圾回收器是无法在内存中回收这个对象。
内存泄露的真因是:持有对象的强引用,且没有及时释放,进而造成内存单元一直被占用,浪费空间,甚至可能造成内存溢出!
 
1.资源对象没关闭造成的内存泄露,try catch finally中将资源回收放到finally语句可以有效避免OOM。资源性对象比如:
(1)Cursor
(2)调用registerReceiver后未调用unregisterReceiver()
(3)未关闭InputStream/OutputStream
(4)Bitmap使用后未调用recycle()
 
2.作用域不一样,导致对象不能被垃圾回收器回收,比如:
(1)非静态内部类会隐式地持有外部类的引用(详情2-1)
(2)Handler造成的内存泄漏(详情2-2)
(3)线程造成的内存泄漏(详情2-3)
(4)Context泄露
 
概括一下,避免Context相关的内存泄露,记住以下事情:
(1)不要保留对Context-Activity长时间的引用(对Activity的引用的时候,必须确保拥有和Activity一样的生命周期)
(2)尝试使用Context-Application来替代Context-Activity
(3)如果你不想控制内部类的生命周期,应避免在Activity中使用非静态的内部类,而应该使用静态的内部类,并在其中创建一个对Activity的弱引用。
    这种情况的解决办法是使用一个静态的内部类,其中拥有对外部类的WeakReference。
(4)Thread 引用其他对象也容易出现对象泄露。
(5)onReceive方法里执行了太多的操作
 
3.内存压力过大
图片资源加载过多,超过内存使用空间,例如Bitmap 的使用
重复创建view,listview应该使用convertview和viewholder
 
4.单例造成的内存泄漏
由于单例的静态特性使得其生命周期和应用的生命周期一样长,如果一个对象已经不再需要使用了,而单例对象还持有该对象的引用,
就会使得该对象不能被正常回收,从而导致了内存泄漏。
 
5.集合容器中的内存泄露
我们通常把一些对象的引用加入到了集合容器(比如ArrayList)中,当我们不需要该对象时,并没有把它的引用从集合中清理掉,
这样这个集合就会越来越大。如果这个集合是static的话,那情况就更严重了。
解决方法:在退出程序之前,将集合里的东西clear,然后置为null,再退出程序。
 
6.WebView造成的泄露
当我们不要使用WebView对象时,应该调用它的destory()函数来销毁它,并释放其占用的内存,否则其长期占用的内存也不能被回收,从而造成内存泄露。
解决方法:为WebView另外开启一个进程,通过AIDL与主线程进行通信,WebView所在的进程可以根据业务的需要选择合适的时机进行销毁,从而达到内存的完整释放。
 
 
 

你可能感兴趣的:(Android,常用)