Java #对象的finalization机制

对象的finalization机制

当对象将被垃圾回收器回收时,在回收之前,先执行对象的 finalization()方法。所以一般不主动调用finalization()方法。如果该对象没有机会被回收,finalization()方法一般没有机会执行。

finalization()是Object类的方法,可以被子类重写。

finalization()方法的执行原理:

1、当obj对象到GC Roots没有引用链时,被标记一次。

2、判断是否执行finalization()方法,如果该对象没有重写finalization()方法,或者finalization()方法已经执行过一次后,则不执行finalization()方法。

3、如果对象objA重写了finalize()方法,且还未执行过,那么objA会被插入到F-Queue队列中,由一个虚拟机自动创建的、低优先级的Finalizer线程触发其finalize()方法执行。

4、finalize()方法是对象逃脱死亡的最后机会,稍后gc会对F-Queue队列中的对象进行第二次标记。如果objA在finalize()方法中与引用链上的任何一个对象建立了联系,那么在第二次标记时,objA会被移出队列。之后,对象会再次出现没有引用存在的情况。在这个情况下,finalize方法不会被再次调用,对象会直接变成不可触及的状态,也就是说,一个对象的finalize方法只会被调用一次。

下面用代码演示该原理:

public class Main {
    public static MyClass1 myClass = null;

    public static void main(String[] args) {
        MyClass1 myClass1 = new MyClass1();
        myClass1.name="name1";
        myClass1=null;
        System.gc();
        try {
            Thread.sleep(2000);//因为Finalizer的优先级很低,所以等待2秒
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(myClass);
        //第二次断开GC Root引用链
        myClass=null;
        System.gc();
        try {
            Thread.sleep(2000);//因为Finalizer的优先级很低,所以等待2秒
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(myClass);
    }
}

public class MyClass1 {

    public static String staticStr = "String";

    public String name;

    @Override
    protected void finalize() throws Throwable {
        System.out.println("MyClass1...finalize方法");
        Main.myClass = this;
    }

    @Override
    public String toString() {
        return "MyClass1{" +
                "name='" + name + '\'' +
                '}';
    }
}

执行结果: 

MyClass1...finalize方法
MyClass1{name='name1'}
null