我对幻像引用的使用感到有些困惑。我读到,只要垃圾收集器喜欢它,就可以收集只有 Phantom 引用指向它们的对象。但是,它没有按我的示例中的预期工作。
import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.util.HashMap;
import java.util.Map;
public class ClassTest {
private static Thread m_collector;
private static boolean m_stopped = false;
private static final ReferenceQueue refque = new ReferenceQueue();
Map<Reference,String> cleanUpMap = new HashMap<Reference,String>();
public void startThread() {
m_collector = new Thread() {
public void run() {
while (!m_stopped) {
try {
Reference ref = refque.remove(1000);
System.out.println(" Timeout ");
if (null != ref) {
System.out.println(" ref not null ");
}
} catch (Exception ex) {
break;
}
}
}
};
m_collector.setDaemon(true);
m_collector.start();
}
public void register() {
System.out.println("Creating phantom references");
class Referred {
}
Referred strong = new Referred();
PhantomReference<Referred> pref = new PhantomReference(strong, refque);
// cleanUpMap.put(pref, "Free up resources");
strong = null;
}
public static void collect() throws InterruptedException {
System.out.println("GC called");
System.gc();
System.out.println("Sleeping");
Thread.sleep(5000);
}
public static void main(String args[]) throws InterruptedException {
ClassTest test= new ClassTest();
test.startThread();
test.register();
test.collect();
m_stopped = true;
System.out.println("Done");
}
}
在上面的示例中,当我运行时,我看到对象“strong”不是自动收集的垃圾。我希望当“强”对象分配给 null 时,该对象会自动收集垃圾。奇怪的是,只有当我在 register 函数中取消注释以下行时,它才会被垃圾收集。
//cleanUpMap.put(pref, "Free up resources");"
这背后的原因是什么?但是,如果我在 Main 函数本身中创建幻像引用,则不会发生此问题。换句话说,当在 main 函数中将“strong”分配给 null 时,对象会自动被垃圾收集,如下面的代码所示。
public static void main(String args[]) throws InterruptedException {
System.out.println("Creating phantom references");
// The reference itself will be appended to the dead queue for clean up.
ReferenceQueue dead = new ReferenceQueue();
PhantomReference<Referred> phantom = new PhantomReference(strong, dead);
strong = null;
// The object may now be collected
System.out.println("Suggesting collection");
System.gc();
System.out.println("Sleeping");
Thread.sleep(5000);
// Check for
Reference reference = dead.poll();
if (reference != null) {
System.out.println("not null");
}
System.out.println("Done");
}
为什么两种情况下的行为不同?