美文网首页
内存泄漏&内存溢出

内存泄漏&内存溢出

作者: WotYang | 来源:发表于2020-06-12 16:01 被阅读0次

    内存泄漏(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退出时记得停止动画
    
    • 内部类的对象被长期持有,那么内部类对象所属的外部类对象也不会被回收

    相关文章

      网友评论

          本文标题:内存泄漏&内存溢出

          本文链接:https://www.haomeiwen.com/subject/nbzgtktx.html