演示代码:
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
public class Main {
public static void main(String[] args) throws InterruptedException {
Object test = new Object();
ReferenceQueue<Object> q = new ReferenceQueue<Object>();
PhantomReference<Object> p = new PhantomReference<Object>(test, q);
Object lock = new Object();
while (true) {
synchronized (lock) {
//q.poll() is null always,why?
if (q.poll() != null) {
break;
}
//System.gc();
lock.wait();
}
}
System.out.println(1111111);
}
}
我测试了代码,但它总是死循环。 代码(System.out.println(1111111);)无法执行,q.poll()reurn null。
我认为如果测试对象被GC删除,q.poll()将返回p对象,然后中断循环,但是调用这个演示代码,它不像我想的那样
编辑: 我修改了演示代码,它现在可以正常工作。
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
public class Main {
public static void main(String[] args) throws InterruptedException {
Object test = new Object();
ReferenceQueue<Object> q = new ReferenceQueue<Object>();
PhantomReference<Object> p = new PhantomReference<Object>(test, q);
Object lock = new Object();
while (true) {
synchronized (lock) {
if (q.poll() != null) {
break;
}
test = null; //it is important
System.gc();
lock.wait(100);//should not lock.wait()
}
}
System.out.println(1111111);
}
}
AS sb说,语句(test = null)是key.GC收集指定null的测试对象。</ p>
答案 0 :(得分:4)
test
变量仍然存在的事实意味着GC永远不会收集它引用的对象...我相信即使局部变量是,JVM也不会收集局部变量引用的任何内容在方法的其余部分中从未提及过。
(此外,当没有任何人正在调用lock.wait()
时,不清楚为什么你使用lock.pulse()
。)
这是适用于我的代码:
import java.lang.Thread;
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
public class Test {
public static void main(String[] args) throws InterruptedException {
Object test = new Object();
ReferenceQueue<Object> q = new ReferenceQueue<Object>();
PhantomReference<Object> p = new PhantomReference<Object>(test, q);
Object lock = new Object();
while (true) {
System.out.println("Checking queue...");
if (q.poll() != null) {
break;
}
System.out.println("Still polling...");
System.gc();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
System.out.println("Interrupted!");
break;
}
// Make the object garbage...
test = null;
}
System.out.println("Finished.");
}
}
答案 1 :(得分:1)
尝试
test = null;
在while循环之前,以便测试对象符合垃圾回收的条件。