【发布时间】:2018-06-18 11:04:16
【问题描述】:
public class Test {
public static void main(String[] args) throws Exception {
A aObject = new A();
ReferenceQueue<A> queue = new ReferenceQueue<>();
PhantomReference<A> weak = new PhantomReference<>(aObject, queue);
aObject = null;
System.gc();
TimeUnit.SECONDS.sleep(1);
System.out.println(queue.poll());
}
}
class A{
@Override
protected void finalize() throws Throwable {
// TODO Auto-generated method stub
super.finalize();
System.out.println("finalize");
}
}
结果是:
finalize
null
但是如果我删除A类中的finalize方法,结果是:
java.lang.ref.PhantomReference@5b2c9e5d
所以,结果显示,当我重写finalize方法时,弱对象没有被放入引用队列,是因为aObject复活了吗?但是我在 finalize 方法中什么也没做
【问题讨论】:
-
一些附加信息:取消注释
super.finalize()或System.out.println(...)不会改变行为。取消注释整个方法会导致预期的行为。将super.finalize()和System.out.println(...)放在if (false) { ... }中也会导致预期的行为,而将这两个语句放在if (true) { ... }中也会导致意外的行为。使用 Oracle java 1.8.0_151 测试。也许这有点用处。 -
您确定这不是由多线程环境中的熵引起的吗?在循环中重复运行此测试是否总是产生相同的结果?
-
@M.Prokhorov 刚刚做了一些测试。在循环中重复代码不会改变结果(我对每个星座重复了 100 次)。该应用程序绝对是单线程的。
-
@Turing85,这与 Javadoc 相矛盾,Javadoc 声明
gc(以及最终的终结器)在与用户启动的线程不同的线程中运行。 -
@M.Prokhorov 它是单线程 w.r.t。用户线程。当然,JVM 确实会产生不受程序员控制的其他线程。