安卓内存溢出和内存泄漏

内存泄漏和内存溢出

一、基本概念:

  1. 内存溢出:OOM(Out Of Memory)。指程序在申请内存时,没有足够的内存空间供其使用,这时系统会抛出OutOfMemory,即内存溢出
  2. 内存泄漏:ML(Memory Leak)。程序向系统申请分配内存后,在使用完毕后未能及时释放内存,导致该内存单元一直被 占据着,无法再次被使用,直到程序结束,这是内存泄漏。一次内存泄漏危害可以忽略,但积累下来就会产生严重的危害,最终会导致内存溢出。

二、内存泄漏的分类:

  1. 常发性内存泄漏:发生内存泄漏的代码会被多次执行,每次执行都会导致一块内存泄漏

  2. 偶发性内存泄漏:某块内存泄漏的代码只有在特定的情况下才会执行,在这种情况下发生的内存泄漏是偶发性的。
    (常发性内存泄漏和偶发性内存泄漏是相对的,在某些情况下常发性可能变为偶发性,偶发性可能变为常发性,因此,测试环境和测试方法就显得尤为重要)

  3. .一次性内存泄漏:发生内存泄露的代码只会被执行一次。

  4. 隐式内存泄漏:程序在工作的过程中不断分配内存,但是直到程序结束的时候才释放内存,这种情况严格的来说不算内存泄漏,程序最终释放了所有内存。但是对于长时间运行的程序,还是会耗尽系统的内存。

从用户使用应用程序的角度来看,一次内存泄漏并不会让用户产生直观地感受,但可怕的是内存泄漏的堆积,内存泄漏堆积过多最终会产生内存溢出,应用程序产生崩溃。这么看来,一次性内存泄漏危害并不大,危害大的是隐式内存泄漏,因为它相对于常发性和偶发性内存泄漏来说更难被发现。

三、安卓中常见的内存泄漏(附图):

在这里插入图片描述

  1. 单例模式在使用Context时,如果使用的是Activity的Context,由于单例模式的生命周期是整个App,因此在Activity退出时,单例还持有改Activity的引用,导致Activity无法被销毁,产生内存泄漏。如果单例模式需要使用Context,推荐使用ApplicationContext或者使用WeakReference来保存Activity的Context对象。
  2. 非静态内部类和匿名内部类会默认持有外部类的引用。一般我们在使用Handler的时候是直接new一个匿名内部类,或者创建一个非静态内部类,此时Handler就会持有外部类的引用。Handler存在于消息队列中会导致外部类的引用一直存在,产生内存泄漏。
  3. 注册和取消注册成对出现。例如广播的注册和取消注册,EventBus的注册和去下注册等。
  4. 集合在使用完毕之后清空并置为null,便于集合中的对象被回收
  5. 使用WebView产生的内存泄漏,在Activity退出时销毁WebView
  6. 使用线程产生的内存泄漏。我们一般使用线程时使用的的是匿名内部类的,会持有外部类的引用,当Activity退出时。如果线程还在运行,此时ctivity无法被正常销毁,产生泄漏。
  7. 一些资源使用完毕记得关闭或者回收,包括Cursor,File,Bitmap,io,TypeArray。

四、Handler的使用优化:

  private static class MyHandler extends Handler{
        private final WeakReference<MainActivity> mActivitys;
        public MyHandler(MainActivity activity) {
            super();
            mActivitys = new WeakReference<>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            MainActivity mainActivity = mActivitys.get();
            if (mainActivity != null){

            }
        }
    }



 Handler  handler = new MyHandler(MainActivity.this);
private static final Runnable myRunnable = new Runnable() {
        @Override
        public void run() {

        }
    };
 handler.post(myRunnable);

Handler的使用避免使用匿名内部类以及非静态内部类,如果使用内部类的话推荐使用上面写法,将内部类写为静态(static)的,并且使用软引用管理Activity对象。或者直接创建外部类来使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值