美文网首页Android面试
面试:内存泄漏与内存溢出

面试:内存泄漏与内存溢出

作者: 天涯的尽头s风沙 | 来源:发表于2019-07-21 09:00 被阅读0次

    什么是内存泄漏?

    答:在程序开发中,当一个对象已经不需要再使用,本该被回收时,而另外一个正在使用的对象持有它的引用从而导致它不能被回收,这就导致本该被回收的对象不能被回收而停留在堆内存中,内存泄漏就产生了。

    内存泄漏的危害?

    答:它是造成应用程序OOM的主要原因之一。由于Android系统为每个应用程序分配的内存有限,当一个应用中产生的内存泄漏比较多时,就难免会导致应用所需要的内存超过这个系统分配的内存限额,这就造成了内存溢出而导致应用Crash。

    内存泄漏的场景:

    • Activity和View
    • 单例模式
      解决办法:将静态单例中持有的Activity的Context改为Application的Context。
      context.getApplicationContext();
    • 线程
      原因:异步任务和Runnable都是一个匿名内部类,默认持有一个当前Activity的隐式引用, 如果Activity在销毁之前,任务还未完成, 那么将导致Activity的内存资源无法回收,造成内存泄漏。
      解决办法: 使用静态内部类
    • 静态变量
    • 非静态内部类创建静态实例
      原因:非静态内部类默认会持有外部类的引用,而又使用了该非静态内部类创建了一个静态的实例,该实例的生命周期和应用的一样长,这就导致了该静态实例一直会持有该Activity的引用,导致Activity的内存资源不能正常回收。
      解决办法: 将该内部类设为静态内部类或将该内部类抽取出来封装成一个单例,如果需要使用Context,使用ApplicationContext。
      Handler:
      原因:同非静态内部类创建静态实例, 那么当这个Activity退出时,消息队列中还有未处理的消息或者正在处理消息,而消息队列中的Message持有mHandler实例的引用,mHandler又持有Activity的引用,所以导致该Activity的内存资源无法及时回收,引发内存泄漏。
      解决办法:
      创建一个静态Handler内部类,然后对Handler持有的对象使用弱引用
      使用mHandler.removeCallbacksAndMessages(null);是移除消息队列中所有消息和所有的Runnable。当然也可以使用mHandler.removeCallbacks();或mHandler.removeMessages();来移除指定的Runnable和Message。
    • 未取消注册或回调
    • Timer和TimerTask
    • 集合中对象未清理
    • 资源未关闭或释放
      对于使用了BraodcastReceiver,ContentObserver,File,Cursor,Stream,Bitmap等资源的使用,应该在Activity销毁时及时关闭或者注销,否则这些资源将不会被回收,造成内存泄漏。
    • 属性动画
      原因: 无限循环动画,如果在Activity中播放这类动画并且在onDestroy中没有去停止动画,那么这个动画将会一直播放下去,这时候Activity会被View所持有,从而导致Activity无法被释放。
      解决办法: 在Activity中onDestroy去调用objectAnimator.cancel()来停止动画。
    • WebView
    • 第三方库使用不当
      对于EventBus,RxJava等一些第三开源框架的使用,若是在Activity销毁之前没有进行解除订阅将会导致内存泄漏。

    什么是内存溢出 ?

    指程序申请内存时,没有足够的内存供申请者使用,或者说,给了你一块存储int类型数据的存储空间,但是你却存储long类型的数据,那么结果就是内存不够用,此时就会报错OOM,即所谓的内存溢出。

    内存泄漏的堆积最终会导致内存溢出

    相关文章

      网友评论

        本文标题:面试:内存泄漏与内存溢出

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