美文网首页先利器
Android内存基础知识

Android内存基础知识

作者: 梦半觉 | 来源:发表于2017-02-09 22:19 被阅读6次

    1.四种引用类型

    1)强引用(Strong Reference) 就是为刚被new出来的对象所加的引用,它的特点就是,生命周期长,不会因为内存紧张而被回收。

    Object obj = new Object(); // 强引用 
    Object objRef = obj; // 强引用
    

    2)软引用(Soft Reference) 声明为软引用的类,是可被回收的对象,如果JVM内存并不紧张,这类对象可以不被回收,如果内存紧张,则会被回收。此处有一个问题,既然被引用为软引用的对象可以回收,为什么不去回收呢?其实我们知道,Java中是存在缓存机制的,就拿字面量缓存来说,有些时候,缓存的对象就是当前可有可无的,只是留在内存中如果还有需要,则不需要重新分配内存即可使用,因此,这些对象即可被引用为软引用,方便使用,提高程序性能。

    Object obj = new Object(); // 强引用 
    Object objRef = new SoftReference(obj); // 软引用 
    if (null != objRef) { 
    obj = objRef.get(); // 获取对象,如果对象已被回收,obj为null 
    }
    

    3)弱引用(Weak Reference) 弱引用的对象就是一定需要进行垃圾回收的,不管内存是否紧张,当进行GC时,标记为弱引用的对象一定会被清理回收。

    Object obj = new Object(); // 强引用 
    Object objRef = new WeakReference(obj); // 弱引用 
    if (null != objRef) { 
    obj = objRef.get(); // 获取对象,如果对象已被回收,obj为null 
    }
    

    4)虚引用(Phantom Reference) 虚引用弱的可以忽略不计,JVM完全不会在乎虚引用,其唯一作用就是做一些跟踪记录,辅助finalize函数的使用。

    Object obj = new Object(); // 强引用 
    ReferenceQueue rq = new ReferenceQueue(); 
    PhantomReference objRef= new PhantomReference(obj, rq); 
    objRef.get(); // always null
    

    2.垃圾回收机制

    这边就简单说下Android目前的垃圾回收机制。 垃圾回收机制用于回收heap中的不再使用的对象,不同的JVM,垃圾回收机制也有所不同。JVM通常会使用Generation机制进行垃圾回收,分为三代:年轻代,年老代和永久代。 一般新对象都会分派到年轻代中,如局部对象等,大部分对象也会在年轻代中被回收。年轻代中有3个内存块,其中From和To是2个survivor内存块,From存放从Eden中存活下来的对象,To存放从From存活下来的对象,年轻代中未回收的对象会被复制到年老代中。每当内存块满的时候就会进行内存回收,年轻代中的内存回收只针对当前内存块进行回收,年老代的内存回收针对整个heap回收,年老代的内存回收会比较慢。 经典的垃圾回收算法是引用计数算法,iOS的OC正是采用此算法。它为每个对象添加一个引用计数器,每被引用一次,计数器加1,失去引用,计数器减1,当计数器在一段时间内保持为0时,该对象就认为是可以被回收得了。但是,这个算法有明显的缺陷:当两个对象相互引用,但是二者已经没有作用时,按照常规,应该对其进行垃圾回收,但是其相互引用,又不符合垃圾回收的条件,因此无法完美处理这块内存清理,因此Dalvik并没有采用引用计数算法来进行垃圾回收。而是采用一个叫:根搜索算法,如下图: 这里写图片描述

    基本思想就是:从一个叫GC Roots的对象开始,向下搜索,如果一个对象不能到达GC Roots对象的时候,说明它已经不再被引用,即可被进行垃圾回收(此处 暂且这样理解,其实事实还有一些不同,当一个对象不再被引用时,并没有完全“死亡”,如果类重写了finalize()方法,且没有被系统调用过,那么系统会调用一次finalize()方法,以完成最后的工作,在这期间,如果可以将对象重新与任何一个和GC Roots有引用的对象相关联,则该对象可以“重生”,如果不可以,那么就说明彻底可以被回收了),如上图中的Object5、Object6、Object7,虽然它们3个依然可能相互引用,但是总体来说,它们已经没有作用了,这样就解决了引用计数算法无法解决的问题。 GCRoot 都有哪些?


    1、 Class:由系统的类加载器加载的类对象
    2、 Static Fields
    3、 Thread:活着的线程
    4、 Stack Local: java方法的局部变量或参数
    5、 JNI Local: JNI方法中的局部引用
    6、 JNI Global: 全局的JNI引用
    7、 Monitor used: 用于同步的监控对象


    相关文章

      网友评论

        本文标题:Android内存基础知识

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