【发布时间】:2017-05-14 18:27:15
【问题描述】:
据我了解,检测对象何时被收集并且内存已经为弱/软引用释放的工作用例会轮询此队列,当引用出现在队列中时,我们可以确定内存是空闲的。
WeakReference ref = new WeakReference (new Object())
为什么我不能轮询ref 并检查它是否变为空?
附言
根据评论中提供的链接:
如果垃圾收集器发现一个弱可达的对象, 发生以下情况: 1.设置WeakReference对象的引用字段 为 null,从而使其不再引用堆对象。
2.被WeakReference引用的堆对象是 宣布可终结。 3.堆对象的finalize()方法运行时 并且它的内存被释放,WeakReference 对象被添加到它的 ReferenceQueue(如果存在)。
因此,如果本文写的是事实,并且这些步骤有序的弱引用在步骤后变为空,但对象仅在第 3 步时才添加到队列中。
这是真的吗?
是什么原因?
让我们研究代码:
工作规范示例:
public class TestPhantomRefQueue {
public static void main(String[] args)
throws InterruptedException {
Object obj = new Object();
final ReferenceQueue queue = new ReferenceQueue();
final WeakReference pRef =
new WeakReference(obj, queue);
obj = null;
new Thread(new Runnable() {
public void run() {
try {
System.out.println("Awaiting for GC");
// This will block till it is GCd
Reference prefFromQueue;
while (true) {
prefFromQueue = queue.remove();
if (prefFromQueue != null) {
break;
}
}
System.out.println("Referenced GC'd");
System.out.println(pRef.get());
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
// Wait for 2nd thread to start
Thread.sleep(2000);
System.out.println("Invoking GC");
System.gc();
}
}
这段代码输出:
Awaiting for GC
Invoking GC
Referenced GC'd
null
好的,我明白它为什么起作用了。
让我们稍微修改一下代码:
public class TestPhantomRefQueue {
public static void main(String[] args)
throws InterruptedException {
Object obj = new Object();
final ReferenceQueue queue = new ReferenceQueue();
final WeakReference pRef =
new WeakReference(obj, queue);
obj = null;
new Thread(new Runnable() {
public void run() {
try {
System.out.println("Awaiting for GC");
while (true) {
if (pRef.get() == null) {
Thread.sleep(100);
break;
}
}
System.out.println("Referenced GC'd");
System.out.println(pRef.get());
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
// Wait for 2nd thread to start
Thread.sleep(2000);
System.out.println("Invoking GC");
System.gc();
}
}
这个变体挂在while循环中并输出:
Awaiting for GC
Invoking GC
请解释这种行为。
【问题讨论】:
-
@Margaret Bloom 看起来不重复
-
那我的错!你能把问题说得更具体一点吗?也许举个例子?
-
可以this link 帮忙吗? "因此,当 WeakReference 或 SoftReference 类的 get() 方法返回 null 时,您知道一个对象已被声明为 finalizable,并且可能但不一定是回收的。只有当 finalization 完成并且堆对象的内存是收集的是放置在其关联 ReferenceQueue 上的 WeakReference 或 SoftReference。"
-
@Margaret Bloom 靠近一点,我需要先阅读
标签: java concurrency garbage-collection weak-references