如果在内存泄漏后再去找原因修复比较困难而且会增加开发成本,所以需要在开发的时候就应该考虑内存问题,下面列出一些常见的内存泄漏场景:
1.资源性对象为关闭
资源性对象(如Cursor、File等)往往都会使用缓冲,她们缓存不只存于java虚拟机内,还存在java虚拟机外,如果只是设置为null,而不关闭她们就会内存泄漏,所以在引用最后先调用她的close()然后再设置为null。
2.注册的对象未注销
对象注册后未注销,会导致观察者列表中持有对象引用,阻止垃圾回收,一般是发生在广播、注册观察者等。假如在Activity的oncreate中监听PhoneStateListener对象,应该在ondestory中取消注册,假如忘记取消注册,就会导致Activity无法被GC回收。
3.类的静态变量持有大数据对象
静态变量不会被销毁,除非应用被杀死,如果静态变量持有大数据对象,如Bitmap等,就会引发内存泄漏。
4.非静态内部类的静态实例
非静态内部类会维持一个到外部类的实例,如果非静态内部类内部有一个实例是静态的就会间接长期持有外部类的应用,阻止外部类被系统GC回收。
5.Handler临时性内存泄漏
Handler发送的message储存在MessageQueue中,有些messgae不会被马上处理掉,假如在Activity退出时的时候此messgae还是没有被处理或者正在被处理就会持有Activity的handler导致Activity或者Service不会被回收,避免此类情况的内存泄漏修改如下:
1)使用一个静态Handler内部类,然后对Handler持有的对象使用弱引用;
2)在Activity的onDestroy或者Stop时,移除消息队列中的消息,避免Looper中有待处理的消息;
代码如下:
private NewHandler mNewHandler = new NewHandler(this);
private static class NewHandler extends Handler{
private WeakReference<Context> mContext = null;
public NewHandler(Context ctx){
mContext = new WeakReference<Context>(ctx);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
mNewHandler.removeCallbacksAndMessages(null);
}
6.容器中的对象没清理造成内存泄漏
把一些对象引用假如到集合中,不需要时,如果没有从集合中移除,此集合就会越来越大,假如是static,情况就会更严重。
7.Webview
在应用中使用一次Webview内存就不会被释放,通常解决办法是为Webview单独开一个进程,用AIDL通信,webview进程根据业务需要进行销毁,达到正常释放内存目的。