jvm虚拟机finalization机制,判断对象是否存活

01 介绍

在垃圾回收之前 会调用对象的finalize()
finalize()是bject类的方法,子类重写finalize()在对象被回收时进行资源的释放和清理工作,如关闭文件/套接字/数据库连接等

程序员不要主动调用finalize(),jvm的垃圾回收机制会调用,原因如下
        finalize()可能会到导致对象复活
        finalize()执行没有保障,执行这个方法的线程优先级比较低,极端情况下如不发生GC,finalize()没有执行机会
        糟糕的finzlize()会严重影响GC性能

02 对象状态

         (1)  可触及的     从根节点开始可以到达这个对象  可达的  不能回收
        (2)  可复活的     对象的所有引用都被释放  但对象可能在finalize()中复活
        (3)  不可触及的  对象的finalize()被调用 并且没有复活 
                                不可触及的永远不可能被复活 因为finalize()只会被调用一次
                                这个状态的对象可以被回收

         以上3种状态是由于finalize()方法的存在
         只有在对象不可触及时才可以被回收

03 过程

判定一个对象是否可回收 , 或经历下面几个过程(两次标记)

   (1)  若对象到GC Root没有引用链,则进行第一次标记
   (2)  若对象没有重写fialize()或已经被调用过了,则对象被判定为不可触及
   (3)  若对象重写finalize()且未执行过,对象被插入到F-Quene队列中 ,由虚拟机创建的低优先级Finalizer线程触发finalize()
   (4)  finalize()是对象逃脱死亡的最后机会,GC会对F-Quene队列中的对象进行第二次标记,在finalize()中若对象与引用链上任何一个对象建立了联系,在第二次标记时对象会被移除
   (5) 之后若对象再次不可达,finalize()已经被调用过了不能再调用了,对象就变成不可触及的状态了

04 复活代码

public class FinalizationTest {
    public static FinalizationTest obj;
    @Override
    protected void finalize() throws Throwable {
        obj = this;
    }
    public static void main(String[] args) {
        try {
            obj = new FinalizationTest();
            obj = null;
            System.gc();
            System.out.println("第1次gc");
            // 因为Finalizer线程优先级很低,暂停2秒,以等待它
            Thread.sleep(2000);
            if (obj == null) {
                System.out.println("obj is dead");
            } else {
                System.out.println("obj is still alive");
            }
            System.out.println("第2次gc");
            obj = null;
            System.gc();
            // 因为Finalizer线程优先级很低,暂停2秒,以等待它
            Thread.sleep(2000);
            if (obj == null) {
                System.out.println("obj is dead");
            } else {
                System.out.println("obj is still alive");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

第1次gc
obj is still alive
第2次gc
obj is dead

04 注意

  Finalizer线程去执行它们的finalize() , 这里所说的“执行”是指虚拟机会触发这个方法开始运行, 但并不承诺一定会等待它运行结束。 这样做的原因是, 如果某个对象finalize()方法执行缓慢, 或更极端地发生了死循环, 很可能导致F-Queue队列中的其他对象永久处于等待, 甚至导致整个内存回收子系统的崩溃

版权声明:本文为qq_37335180原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。