内存泄漏和内存溢出的关系
- 内存泄漏: 是指申请空间后,在使用完后没有释放。
- 内存溢出: 程序向系统申请的内存超过了内存所能分配的大小(OOM)。
- 内存泄漏会导致程序运行变慢,影响体验程度。大量的内存泄露会导致内存溢出(oom)。
内存泄漏的主要原因
- 持有对象的强引用,没有及时释放
导致内存泄漏的案例分析
- 写单列工具类,如:
private static WifiUtils mInstant = null; //全局静态变量
public static WifiUtils getInstant(Context context) {
if (mInstant == null) {
synchronized (WifiUtils.class) {
if (mInstant == null) {
mInstant = new WifiUtils(context);
}
}
}
return mInstant;
}
上面可能是我们写的一个获取单列引用的方法,单独这样看应该没有任何问题。但是当我们在activity中去调用
WifiUtils.getInstant(this)
这样就会造成内存泄漏了。
1. 原因:
WifiUtils的对象是全局static的,创建后其生命周期是伴随程序一直存在的。但他保留了activity的一个强引用,所以当activity需退出时,导致无法销毁或被回收。
2.解决方案
解决的方案很多,这里举两种常用的:
( 1 )、把context 改成 context.getApplicationContext()。这样并不是所以的地方度可以这样做,但是一般的工具类可以这样。
(2)、在activity的时候退出,销毁mInstant对象。android中registerListener和unregisterListener 的做法就和这个一样。
编码的时候时刻注意以下容易出现内存溢出的情况
1、带有全局static变量
2、Inner Classes
private static Object inner;
void createInnerClass() {
class InnerClass {
}
inner = new InnerClass();
}
void paly(){
createInnerClass();//创建内部类对象
}
3、Anonymous Classes
void startAsyncTask() {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
while(true);
}
}.execute();
}
void paly(){
startAsyncTask();//task执行任务的时候,activity无法退出,直到任务执行结束
}
4、Threads、TimerTask、Handler 这几个有点类试,都是在执行任务的时候,对activity保持着强引用,所以在退出的时候,要注意销毁,防止内存泄漏。
内存泄漏的规避
内存泄漏无疑会给我们的程序带来诸多的问题。但是,只要我们记住 "当当前的对象要销毁时,没有其他地方对其有强引用,如果有需要先把引用的地方释放或者销毁 ” 这样就会大大减少内存泄漏的几率。