演示代码:
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()返回null。
我认为如果测试对象被GC删除,q.poll()将返回p对象,然后中断循环,但是调用这个演示代码,这并不像我的想法
编辑: 我修改了demo代码,现在可以运行了。
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);
}
}
正如sb所说,语句(test=null)是关键。GC收集分配null的测试对象。</p>
最佳答案
test
变量仍然存在的事实意味着 GC 永远不会收集它引用的对象...我相信 JVM 不会收集局部变量引用的任何内容,即使方法的其余部分永远不会引用局部变量。
(另外,当没有任何东西调用 lock.pulse()
时,还不清楚为什么要使用 lock.wait()
。)
这是适合我的代码:
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.");
}
}
关于java - 为什么 PhantomReference 不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7513571/