我正在尝试使用ReferenceQueue释放由垃圾收集对象使用的资源。问题是,即使有证据证明所引用的对象之一已被垃圾回收,我的引用队列也始终为空。这是一个非常简单,自包含的JUnit测试,它说明了我正在尝试做的事情(跟踪对象的移除):
@Test
public void weakReferenceTest() {
ReferenceQueue<Object> refQueue = new ReferenceQueue<Object>();
Object myObject1 = new Object();
Object myObject2 = new Object();
WeakReference<Object> ref1 = new WeakReference<Object>(myObject1, refQueue);
WeakReference<Object> ref2 = new WeakReference<Object>(myObject2, refQueue);
myObject1 = null;
// simulate the application running and calling GC at some point
System.gc();
myObject1 = ref1.get();
myObject2 = ref2.get();
if (myObject1 != null) {
System.out.println("Weak Reference to MyObject1 is still valid.");
fail();
} else {
System.out.println("Weak Reference to MyObject1 has disappeared.");
}
if (myObject2 != null) {
System.out.println("Weak Reference to MyObject2 is still valid.");
} else {
System.out.println("Weak Reference to MyObject2 has disappeared.");
fail();
}
Reference<? extends Object> removedRef = refQueue.poll();
boolean trackedRemoval = false;
while (removedRef != null) {
if (removedRef == ref1) {
System.out.println("Reference Queue reported deletion of MyObject1.");
trackedRemoval = true;
} else if (removedRef == ref2) {
System.out.println("Reference Queue reported deletion of MyObject2.");
fail();
}
removedRef = refQueue.poll();
}
if (trackedRemoval == false) {
fail();
}
}
对我来说,这总是打印:
Weak Reference to MyObject1 has disappeared.
Weak Reference to MyObject2 is still valid.
...很好,但是由于
trackedRemoval
最后是false
,因此测试始终失败-ReferenceQueue
始终为空。我在使用
ReferenceQueue
和/或WeakReference
错误吗?我也尝试使用PhantomReference
代替,但这没什么区别。有趣的是,如果将单元测试转换为常规的
public static void main(String[] args)
方法,则它就像一个魅力!谁能解释这个特定行为?我一直在寻找答案已经有一段时间了。
最佳答案
对我来说,这似乎是一种比赛条件。当GC确定myObject1
引用的对象是GCable时,它将对其进行GC并从WeakReference
中清除它。然后它将把WeakReference
添加到“待处理的引用列表”中。有一个引用处理程序线程将从该列表中删除并添加到适当的ReferenceQueue
中。以上是支持javadoc的实现细节
在同一时间或以后,它将把那些
通过参考注册的新清除的弱参考
队列。
当代码到达时
Reference<? extends Object> removedRef = refQueue.poll();
引用处理程序线程必须未将
WeakReference
添加到ReferenceQueue
中,因此poll
返回null
。关于java - 为什么ReferenceQueue始终为空?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25998367/