gpt4 book ai didi

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

转载 作者:搜寻专家 更新时间:2023-11-01 00:50:53 25 4
gpt4 key购买 nike

这是我的代码

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();
}
}
}

很奇怪,rq.remove()会永远被阻塞。为什么我的可终结对象的虚引用不能放入引用队列?是否被GC回收?

最佳答案

问题出在您的重要 finalize() 方法上。在默认实现中(在 Object 类中)这个方法实际上是空的。当它的实现不为空时,则不能保证在调用 finalize() 后立即收集对象。

如果您将以这种方式修改您的程序:

    for (int i = 0; i  < 1000; i++)
System.gc();

即你会多次调用 GC - 这可能导致 rq 对象被完全收集(在我的机器上测试)。

此外,我建议您点击以下链接进行探索:

  1. Java: PhantomReference, ReferenceQueue and finalize
  2. Discovering Objects with Non-trivial Finalizers
  3. The Secret Life Of The Finalizer: page 2 of 2

UPD: 另一种方式:您必须牢记,重要的 finalize() 方法由特殊的 Finalizer-Thread 调用,它也必须是集。因此,对于完整的 pr 收集,您可以执行以下操作:

a) 在 Main 方法中创建标志:

public static volatile boolean flag;

b) 在 finalize() 方法中设置标志:

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

c) 检查标志是否为真,然后再次调用 gc():

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

关于java - 为什么我不能从 ReferenceQueue 中获取可终结对象的 PhantomReference?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17850978/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com