含义“对于任何给定对象,JVM永远不会多次调用finalize方法。”万一对象复活?

时间:2018-10-14 05:35:45

标签: java finalizer

根据Java文档:

对于任何给定对象,Java虚拟机都不会多次调用finalize方法。

  1. 以上政策可以帮助使物体永生吗?如果我从finalize()方法中一次复活了一个对象,那么该对象将成为不朽的,因为JVM无法再次在该对象上调用finalize()方法吗?

OR

  1. 如果该对象再次符合GC的条件(假设另一个指向已恢复对象的引用也符合GC的条件),那么下一次JVM将删除该对象而无需调用该对象的finalize()方法吗?

我试图通过一些示例代码来验证它,并假设第二个是正确的,但是需要确认以供我理解。

1 个答案:

答案 0 :(得分:0)

按照ernest_k 它是2。该对象将被垃圾回收,而无需调用finalize()方法。

添加示例代码以完成此答案,我创建了该代码以进行验证。

import java.util.HashSet;
import java.util.Set;

class Immortal {

    // making it public and non-fianl to modify from outside
    public static Set<Immortal> immortals = new HashSet<>();

    @Override
    protected void finalize() throws Throwable {
        System.out.println("Running finalize for " + this);
        immortals.add(this); // Resurrect the object by creating a new reference
    }
}

public class ObjectResurrection {

    public static void callGC() {
        // call garbage collection
        System.gc();

        // wait for some time to give chance to run garbage collection thread
        try {
            Thread.sleep(10 * 1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        Immortal immortal1 = new Immortal();
        Immortal immortal2 = new Immortal();

        // print objects when they are alive.
        System.out.println("immortal1 = " + immortal1);
        System.out.println("immortal2 = " + immortal2);

        // print immortal set
        System.out.println("immortal set = " + Immortal.immortals);

        // make all objects garbage collectable
        immortal1 = null;
        immortal2 = null;

        callGC();

        // now objects will be null
        System.out.println("immortal1 = " + immortal1);
        System.out.println("immortal2 = " + immortal2);

        // but stays in immortal set
        System.out.println("immortal set = " + Immortal.immortals);

        // remove all objects from immortal set, and make them again eligible for GC
        Immortal.immortals.clear();

        callGC();

        // again print the immortal set
        // this time set will be empty, and those 2 objects will be destroyed by Garbage
        // Collection,
        // but this time they will not call finalize, because it is already called
        // you can notice no output from finalize method in the output this time
        System.out.println("immortal set = " + Immortal.immortals);
    }

}

上述程序的输出(在我的机器上):

immortal1 = effective.java.item7.finalizer6.Immortal@70dea4e
immortal2 = effective.java.item7.finalizer6.Immortal@5c647e05
immortal set = []
Running finalize for effective.java.item7.finalizer6.Immortal@5c647e05
Running finalize for effective.java.item7.finalizer6.Immortal@70dea4e
immortal1 = null
immortal2 = null
immortal set = [effective.java.item7.finalizer6.Immortal@5c647e05, effective.java.item7.finalizer6.Immortal@70dea4e]
immortal set = []