作者热门文章
- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
这是我的代码
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
对象被完全收集(在我的机器上测试)。
此外,我建议您点击以下链接进行探索:
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/
据我所知,不能保证 Object.finalize() 总是被调用。但是如果有重要的非GC资源,并且用户没有意外调用close(),我该如何释放该资源?PS。 .NET中的Object.Finaliz
我是一名优秀的程序员,十分优秀!