看似没有用处的虚引用,有什么用途呢?
1.首先,我们可以通过虚引用知道对象究竟什么时候真正从内存里面移除的,而且这也是唯一的途径。
2.虚引用避过了finalize()方法,因为对于此方法的执行而言,虚引用真正引用到的对象是异常对象,若在该方法内要使用对象只能重建。一般情况垃圾回收器会轮询两次,一次标记为finalization,第二次进行真实的回收,而往往标记工作不能实时进行,或者垃圾回收其会等待一个对象去标记finalization。这种情况很有可能引起MemoryOut,而使用虚引用这种情况就会完全避免。因为虚引用在引用对象的过程不会去使得这个对象由Dead复活,而且这种对象是可以在回收周期进行回收的。
在JVM内部,虚引用比起使用finalize()方法更加安全一点而且更加有效。而finaliaze()方法回收在虚拟机里面实现起来相对简单,而且也可以处理大部分工作,所以我们仍然使用这种方式来进行对象回收的扫尾操作,但是有了虚引用过后我们可以选择是否手动操作该对象使得程序更加高效完美。
3.Java里面对象的生命周期
在JVM运行空间里面,对象整个声明周期大致分为以下几个阶段:
创建阶段(Creating)->应用阶段(Using)->不可视阶段(Invisible)->不可达阶段(Unreachable)->可收集阶段(Collected)->终结阶段(Finalized)->释放阶段(Free)
【1】创建阶段:
创建过程需要经过其中几步:
为对象分配内存空间
开始构造对象
递归调用超类的构造方法
进行对象实例初始化和变量初始化
执行构造方法体
【2】应用阶段特征:
系统至少维护着对象的一个强引用(StrongReference)
所有该对象的引用全部是强引用,除非我们显示声明了软引用、弱引用或者虚引用
【3】不可是视阶段:
不可视阶段就是我们在区域代码中不可以再引用它,就是强引用已经消失,一般情况我们把这个时候的对象设置为null,其主要目的是让JVM发现它,并且可以及时回收该对象所占用资源
【4】不可到达阶段:
不可达阶段的对象,在虚拟机所管理的对象引用根集合中再也找不到直接或间接的强引用,这些对象通常是指所有线程栈中的临时变量以及相关引用,这种对象都是要预备回收的对象,但是这时候不能被GC直接回收。
【5】可收集阶段、终结阶段、释放阶段:
对象生命周期最后一个阶段,这种阶段的对象可能处于三种状态:
垃圾回收器发现对象已经不可达
finalize方法已经被执行
对象已经被重用
摘自 chenghai2011的专栏