Java 为什么我不能从可终结对象的ReferenceQueue中获取PhantomReference?

Java 为什么我不能从可终结对象的ReferenceQueue中获取PhantomReference?,java,reference,finalize,Java,Reference,Finalize,这是我的密码 public class FinalizableObject { @Override protected void finalize() throws Throwable { System.out.println("finalize() invoked for " + this); super.finalize(); } } public class Main { private static void test(

这是我的密码

public class FinalizableObject {

    @Override
    protected void finalize() throws Throwable {
        System.out.println("finalize() invoked for " + this);
        super.finalize();
    }
}

public class Main {
    private static void test() throws InterruptedException {
        ReferenceQueue<FinalizableObject> rq = new ReferenceQueue<FinalizableObject>();
        FinalizableObject obj = new FinalizableObject();
        PhantomReference<FinalizableObject> pr1 = new PhantomReference<FinalizableObject>(obj, rq);
        obj = null;
        System.gc();
        Reference<? extends Object> ref = rq.remove();
        System.out.print("remove " + ref + " from reference queue\n");
    }
    public static void main(String[] args) {
        try {
            test();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
公共类FinalizableObject{
@凌驾
受保护的void finalize()抛出可丢弃的{
System.out.println(“为“+this”调用finalize());
super.finalize();
}
}
公共班机{
private static void test()引发InterruptedException{
ReferenceQueue rq=新的ReferenceQueue();
FinalizableObject obj=新的FinalizableObject();
PhantomReference pr1=新的PhantomReference(obj,rq);
obj=null;
gc();

Reference问题在于非平凡的
finalize()
方法。在默认实现中(在类
Object
中),此方法实际上是空的。如果其实现不是空的,则不能保证调用
finalize()
后立即收集对象

如果要以这种方式修改程序:

    for (int i = 0; i  < 1000; i++)
        System.gc();
b) 在
finalize()
方法中设置标志:

public static volatile boolean flag;
@Override
protected void finalize() throws Throwable {
    System.out.println("finalize() invoked for " + this);
    super.finalize();
    Main.flag = true;
}
c) 检查标志是否为true,然后再次调用
gc()

    System.gc();
    while (!flag) Thread.sleep(10);
    System.gc();

非常感谢。
我知道FinalizerReferenceQueue和FinalizerDeamon,2次GC可以完全收集一个可完成的对象。但是我不明白为什么100次GC会触发收集它(即使是20次GC也不能触发队列).
另一方面,如果我用WeakReference替换PhantomReference,它可以很快删除引用。
@DevboardFan这是因为调用非平凡的
finalize()
method JVM构造特殊的终结器线程,这些线程也必须被收集和完成。@DevboardFan顺便说一句,您可以创建
public static volatile boolean标志;
Main()
类中,在
finalize()
方法中设置此标志,然后在
Main()
中等待,直到设置此标志(在第一次
之后)
)。之后,您可以再次调用
System.gc()
。这就足够了。我明白了。您的意思是finalize()方法将在一次gc后调用,但对象仍然没有真正回收(从堆中)。我很奇怪,为什么它需要这么多gc来触发真正的回收过程(而不是调用finalize()).再次感谢你。