内存泄漏(memory leak)
申请了内存使用完毕后,并没有进行释放,这些未释放的内存称之为内存泄漏。
举个例子:申请了10M的内存使用,但是分配了6M去使用不进行回收,那么就只剩下4M的内存可供使用,就仿佛泄漏掉了6M内存。
内存溢出(out of memory)(OOM)
申请内存时,没有足够的内存可供使用,则导致内存溢出。
继续引用上面的例子,由于内存泄漏占用了6M内存,导致可供使用内存剩余4M,这个时候申请了5M内存,最终由于内存不够使用,从而导致内存溢出。
由此可见,内存泄漏最终会导致内存溢出。
下面举几个常见的内存溢出情况:
- 循环过多或死循环,产生大量对象
- 静态集合引起的内存溢出(因为静态集合的生命周期和 JVM 一致,导致静态集合引用的对象不能释放)
例子如下:
public class OOM {
static List list = new ArrayList();
public void oomTests(){
Object obj = new Object();
list.add(obj);
}
}
解决方案就是在用完后,进行集合清除以及置空,如下
OOM.list.clear();
OOM.list = null;
- 单例模式(和静态集合导致内存泄漏的原因相似,因为单例的静态特性也是和 JVM 一致。如果单例对象持有外部对象的引用,那么这个外部对象也不会被回收,那么就会造成内存泄漏)
例子如下:
public class Single {
private static Single instance;
private Context mContext;
public SingleInstanceClass get(Context context) {
if (instance == null) {
instance = new SingleInstanceClass(context);
}
return instance;
}
private Single(Context context) {
this.mContext = context;
}
}
解决方案就是使用 Applicaiton 的 Context,如下
public class Single {
private static Single instance;
private Context mContext;
public SingleInstanceClass get(Context context) {
if (instance == null) {
instance = new SingleInstanceClass(context);
}
return instance;
}
private Single(Context context) {
// 使用 Application 的 Context
this.mContext = context.getApplicationContext(); ;
}
}
我们还可以采用 弱引用(WeakReference) 代替 强引用 持有实例
- 资源使用未释放( 广播BraodcastReceiver、数据连接、IO、Socket连接、图片资源Bitmap等)
解决方案就是在 Activity 销毁时及时关闭 / 注销资源,如下:
// 对于 广播BraodcastReceiver:注销注册
unregisterReceiver()
// 对于 文件流File:关闭流
InputStream / OutputStream.close()
// 对于数据库游标cursor:使用后关闭游标
cursor.close()
// 对于 图片资源Bitmap:Android分配给图片的内存只有8M,若1个Bitmap对象占内存较多,当它不再被使用时,应调用recycle()回收此对象的像素所占用的内存;最后再赋为null
Bitmap.recycle();
Bitmap = null;
// 对于动画(属性动画)
// 将动画设置成无限循环播放repeatCount = “infinite”后
// 在Activity退出时记得停止动画
- 内部类的对象被长期持有,那么内部类对象所属的外部类对象也不会被回收
网友评论