JVM内存分析系列(五)浅谈finalize()方法

根搜索算法中不可达对象在回收之前,要进行二次标记。

第一次标记时会进行一次筛选:筛选的条件是是否有必要执行finalize()方法。

当对象没有覆盖finalize()方法,或者finalize()被虚拟机调用过,则虚拟机认为没有必要执行finalize()方法。

如果这个对象有必要执行finalize(),则会放在一个队列里,以一个低优先级的线程进行执行finalize()方法进行二次标记,如果在finalize()方法中,对象重新回到引用链上(比如this赋值给其他引用链上的对象),则该对象不被回收,而移出该队列。

注意:finalize()方法只被调用一次,如果这个对象在GC时被调用过一次finalize()方法,则第二次GC的时候,就会被判断为没有必要执行finalize()而被直接回收。

另外finalize()能做的所有工作,都可以通过try-finally更好、更及时的解决。所以请忘掉finalize().

package System.gc;

/**
 * @author piaohailin
 * @date   2013-12-28
*/
public class TestGc {
    public static TestGc HOOK;

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        TestGc.HOOK = this;
        System.out.println("finalize");
    }

    /*
          输出结果
    finalize
    HOOK is alvie
    HOOK is dead
     */
    public static void main(String[] args) throws Exception {
        HOOK = new TestGc();
        HOOK = null;
        System.gc();//第一次GC,符合有必要要执行finalize的条件
        Thread.sleep(1000);//Finalizer线程优先级较低,所以要等一会
        if (HOOK != null) {
            System.out.println("HOOK is alvie");
        } else {
            System.out.println("HOOK is dead");
        }

        HOOK = null;
        System.gc();//第二次GC,因为已经执行过一次finalize,所以没有必要进行二次标记
        Thread.sleep(1000);//Finalizer线程优先级较低,所以要等一会
        if (HOOK != null) {
            System.out.println("HOOK is alvie");
        } else {
            System.out.println("HOOK is dead");
        }
    }

}

相关推荐