Dev*_*Fan 5 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() 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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
这很奇怪,rq.remove()将永远被阻止.为什么我的finalizable对象的幻像引用不能放入引用队列?它是否被GC收集?
问题在于你的方法不简单finalize()。在默认实现中(在类中Object)这个方法实际上是空的。当其实现不为空时,不保证调用后会立即收集对象finalize()。
如果您将以这种方式修改您的程序:
for (int i = 0; i < 1000; i++)
System.gc();
Run Code Online (Sandbox Code Playgroud)
也就是说,您将多次调用 GC - 这可能会导致rq对象被完全收集(在我的机器上测试)。
另外,我建议您通过以下链接进行探索:
UPD:另一种方式:您必须记住,非平凡的finalize()方法是由特殊的 Finalizer-Thread 调用的,也必须收集这些方法。因此,为了完整pr收集,您可以执行以下操作:
a) 在方法内创建标志Main:
public static volatile boolean flag;
Run Code Online (Sandbox Code Playgroud)
b) 在方法中设置标志finalize():
@Override
protected void finalize() throws Throwable {
System.out.println("finalize() invoked for " + this);
super.finalize();
Main.flag = true;
}
Run Code Online (Sandbox Code Playgroud)
c) 检查标志是否为 true,然后gc()再次调用:
System.gc();
while (!flag) Thread.sleep(10);
System.gc();
Run Code Online (Sandbox Code Playgroud)