Android中的内存泄漏和内存溢出.md

作者: hongjay | 来源:发表于2018-05-09 15:11 被阅读176次
    概念

    内存泄漏是因为持有对象长期引用,导致对象无法被 GC 回收。

    为了避免这种情况,我们可以选择在对象生命周期结束的时候,解除绑定,将引用置为空,或者使用弱引用。

    例子
    1. 单例模式导致内存泄露
      传入的context为act,但单例的生命周期是app
    2. 非静态内部类、匿名内部类导致内存泄露(静态变量持有Act,非静态内部类的静态实例 )
      它们会隐式的持有外部类的引用,长期持有该引用(比如写个循环)就会导致内存泄漏,使用静态内部类和弱引用来代替它们。(因为静态的内部类不会持有外部类的引用)
    3. Handler导致内存泄漏
      Handler通过发送Message与主线程交互,Message发出之后是存储在MessageQueue中的,有些Message也不是马上就被处理的。
      在Message中存在一个 target,是Handler的一个引用,如果Message在Queue中存在的时间越长,就会导致Handler无法被回收。
      如果Handler是非静态的,(因为持有外部activity的引用)会导致Activity或者Service不会被回收。
    解决方法 :
    • 静态内部类+弱引用
      创建一个静态Handler内部类,然后对Handler持有的对象使用弱引用)
      静态内部类+弱引用。相当于activity没关闭的时候,act有强弱两种引用,关闭的时候,只有弱引用。
    • 非静态内部类+api clean掉message
    1. 线程造成的内存泄漏
      执行一些长期运行的任务,避免在这些任务中持有 Activity 对象的引用,如果持有了引用的话,我们应该在对象生命周期结束的时候,释放引用。
    2. 资源未关闭造成的内存泄漏
      对于使用了BraodcastReceiver,ContentObserver,File,Cursor,Stream,Bitmap等资源的使用,应该在Activity销毁时及时关闭或者注销,否则这些资源将不会被回收,造成内存泄漏。
    LeakCanary

    LeakCanary的内存泄露提示一般会包含三个部分:

    第一部分(LeakSingle类的sInstance变量)引用第二部分(LeakSingle类的mContext变量), 导致第三部分(MainActivity类的实例instance)泄露.

    Java的GC内存回收机制

    当我们向上寻找,一直寻找到GC Root的时候,此对象不会进行回收,例如,一个Activity。那么如果我们向上寻找,直到找到GC Root对象的时候,就说明它是不可以回收的,例如,我定义了一个int a;但是这个数据,我整个页面或者说整个项目都没有用到,则这个对象会被GC掉。

    GC的引用点
    1. java栈中引用的对象

    2. 方法静态引用的对象

    3. 方法常量引用的对象

    4. Native中JNI引用的对象

    5. Thread——“活着的”线程

    内存溢出
    瞬间大内存:图片加载
    内存泄漏和内存溢出区别
    1. 内存溢出是指程序在申请内存的时候,没有足够的内存可以分配,导致Out Of Memory错误,也就是OOM。

    2. 内存泄漏:对象都有生命周期的,在生命周期完成之后,就该被垃圾回收和释放,如果得不到及时的释放,就会一直占用内存,造成内存泄漏。随着内存泄漏的堆积,可能导致oom。

    相关文章

      网友评论

        本文标题:Android中的内存泄漏和内存溢出.md

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