内存泄漏和内存溢出
一、什么是内存泄漏和内存溢出:
1、内存泄漏(memory leak ):指程序申请内存后,无法释放已申请的内存空间,导致系统无法及时回收内存分配给其他程序使用。
2、内存溢出(out of memory):指程序申请内存时,没有足够的内存提供给申请者使用,导致无法正常存储到内存中。例如给了一个int类型的存储空间,却存储long型数据就会发生内存溢出。
二、两者关系和区别:
1.关系:内存泄露最终会导致内存溢出,由于系统中的内存是有限的,如果过度占用资源而不及时释放,最后会导致内存不足,从而无法给所需要存储的数据提供足够的内存,从而导致内存溢出。导致内存溢出也可能是由于在给数据分配大小时没有根据实际要求分配,最后导致分配的内存无法满足数据的需求,从而导致内存溢出。
2.区别:内存泄露是由于GC无法及时或者无法识别可以回收的数据进行及时的回收,导致内存的浪费;内存溢出是由于数据所需要的内存无法得到满足,导致数据无法正常存储到内存中。内存泄露的多次表现就是会导致内存溢出。
三、什么场景会引起内存泄漏
1、静态集合引起内存泄漏
主要是hashmap,Vector等,如果是静态集合 这些集合没有及时setnull的话,就会一直持有这些对象。
2、observer 我们在使用监听器的时候,往往是addxxxlistener,但是当我们不需要的时候,忘记removexxxlistener,就容易内存leak
广播没有unregisterrecevier
3、各种数据链接没有关闭,数据库contentprovider,io,cursor,sokect等
4、非静态内部类:
java中的内部类(匿名内部类),会持有宿主类的强引用this。
所以如果是new Thread这种,后台线程的操作,当线程没有执行结束时,activity不会被回收。
5、单例:
单例中的Context如果传的是Activity,则容易内存泄漏。解决办法使用Application
6、handler造成内存泄漏:
/**
* Handler造成的内存泄露
*/
public class MainActivity extends AppCompatActivity {
private final Handler mLeakyHandler = new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLeakyHandler.postDelayed(new Runnable() {
@Override
public void run() {
}
},1000*60 *10);
finish();
}
/**
* 造成这样的原因是:当Acvitity结束时,handler拿着acitivty的句柄,导致activity不会被释放
* 解决方案:
* 1 将handler声明为静态的
* 2 如果有activity的引用,通过弱引用的方式持有activity
*
*/
private MyHandler myHandler = new MyHandler(this);
private static class MyHandler extends Handler{
private WeakReference reference;
public MyHandler(Context context) {
this.reference = new WeakReference<>(context);
}
@Override
public void handleMessage(@NonNull Message msg) {
MainActivity activity = (MainActivity) reference.get();
if(activity != null){
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
myHandler.removeCallbacksAndMessages(null);
}
}
7、