Java中的引用:算法
Java中将引用分为强引用、软引用、弱引用、虚引用4种,强度依次减弱。 强引用:Object obj = new Object(),只要强引用还存在,垃圾收集器就永远不会回收这些引用关联着的对象。 软引用:用来描述一些还有用但并不是必需的对象。 在系统将要发生内存溢出异常前,垃圾收集器才会去回收这些软引用关联着的对象。jdk1.2以后,提供了SoftReference类来实现软引用。 弱引用:和软引用同样,也是描述一些还有用但并不是必须的对象,只是它的强度更弱一些。 当垃圾收集器工做时,不管当前内存是否够用,都会回收掉只被弱引用关联的对象。jdk1.2以后,提供了WeakReference类来实现软引用。 虚引用:是最弱的一种引用,一个对象是否有虚引用的存在,彻底不会对其生存时间构成影响,也没法经过虚引用来取得一个对象实例。 设置虚引用的惟一目的:在这个对象被垃圾收集器回收时获得一个系统通知。
判断对象是否存活的算法:this
1)引用计数算法: 概念:给对象添加一个引用计数器,每当有一个地方引用它时,计数器就加1;当引用失效时,计数器就减1;当计数器为0时,对象就不能再使用了。 说明:Java虚拟机里面没有采用 引用计数算法 来管理内存。缘由:不能解决对象之间相互循环引用的问题 案例: ReferenceCountingGC{ public Object instance = null; // 这个成员属性的惟一意义就是占用一些内存,以便在GC日志中能够明显地看出是否被回收过 private byte[] bigBlock = new byte[1024 * 1024]; public static void testGC() { ReferenceCountingGC objA = new ReferenceCountingGC(); ReferenceCountingGC bojB = new ReferenceCountingGC(); objA.instance = objB; objB.instance = objA; objA = null; objB = null; // 假设在这行发生GC,那么objA和objB是否被回收呢? System.gc(); } } 由运行结果能够看出:虚拟机并无由于这两个对象相互引用就不去回收它们。说明:虚拟机不是经过引用计数算法来判断对象是不是存活的。 2)可达性分析算法(根搜索算法): 概念:从根节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象与根节点之间不存在任何引用链时,则证实此对象是不可用的。 根对象的断定: 1)虚拟机栈(栈帧中的本地变量表)中引用的对象、本地方法栈中JNI(即native方法)引用的对象。 2)方法区中:类静态属性引用的对象、常量引用的对象。
一个对象被回收要通过两次标记:线程
第一次标记: 若是一个对象在进行可达性分析后没有发现与根对象间存在引用链,那么这个对象将被第一次标记,并进行判断:判断此对象是否有必要去执行finalize()方法。 1)若是:对象没有覆盖finalize()方法,或者finalize()方法已经被调用过了,虚拟机就不会执行该对象的finalize()方法,直接回收该对象。 2)若是:对象覆盖了finalize()方法,而且finalize()方法没有被调用过,那么: 1>这个对象将会放置在一个叫作F-Queue 的队列中,稍后(在第二次标记以前),会有一个由虚拟机自动创建的、低优先级的Finalizer线程去执行该对象的finalize()方法。 2>注意:这里的“执行”是指虚拟机会触发这个方法,可是并不保证会等待这个方法运行结束。缘由:若是某个对象执行finalize()方法花费的时间比较长,或者发生了死循环,这样的话就极可能会致使F-Queue队列中其它的对象永久等待,若是JVM要等待它运行结束,则有可能会致使整个内存回收系统崩溃。 第二次标记: 在第一次标记后,GC将对 F-Queue 中的对象进行第二次标记,若是对象在finalize()方法中成功拯救本身,那么这个对象将被移出”即将回收“的那个集合。若是没有在finalize()方法中救出本身,那么它将被GC回收。 注:在finalize()方法中拯救本身的方法:只要从新与引用链上的任何一个对象创建关联便可。例如:将本身(this)赋值给某个对象的成员变量。