当引用对象是类中的字段时,我遇到了幻像引用的问题。当类对象设置为 null 时,GC 不会自动收集字段
控制器.java
public class Controller {
public static void main( String[] args ) throws InterruptedException
{
Collector test = new Collector();
test.startThread();
Reffered strong = new Reffered();
strong.register();
strong = null; //It doesn't work
//strong.next =null; //It works
test.collect();
Collector.m_stopped = true;
System.out.println("Done");
}
}
Collector.java:我有一个收集器,它将一个对象注册到引用队列并在收集时打印它。
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 Collector {
private static Thread m_collector;
public static boolean m_stopped = false;
private static final ReferenceQueue refque = new ReferenceQueue();
Map<Reference,String> cleanUpMap = new HashMap<Reference,String>();
PhantomReference<Reffered> pref;
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(Test obj) {
System.out.println("Creating phantom references");
//Referred strong = new Referred();
pref = new PhantomReference(obj, refque);
cleanUpMap.put(pref, "Free up resources");
}
public static void collect() throws InterruptedException {
System.out.println("GC called");
System.gc();
System.out.println("Sleeping");
Thread.sleep(5000);
}
}
引用.java
public class Reffered {
int i;
public Collector test;
public Test next;
Reffered () {
test= new Collector();
next = new Test();
}
void register() {
test.register(next);
}
}
测试是一个空类。我可以看到当 Reffered 对象设置为 null 时,不收集 Refferred 类中的“下一个”字段。换句话说,当“strong”设置为空时,不收集“next”。我假设“next”将由 GC 自动收集,因为当“strong”设置为 null 时不再引用“next”。但是,当“strong.next”设置为null时,“next”就如我们所想的那样被收集。为什么strong设置为null时不会自动收集“next”?