I am having problems with Phantom References when referents are the fields inside the class. When class objects are set to null, fields are not collected automatically by GC
Controller.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: I am having a Collector that registers an object to reference queue and prints it when it is collected.
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);
}
}
Reffered.java
public class Reffered {
int i;
public Collector test;
public Test next;
Reffered () {
test= new Collector();
next = new Test();
}
void register() {
test.register(next);
}
}
Test is a empty class. I can see that "next" field in Refferred class is not collected when Reffered object is set to null. In other words, when "strong" is set to null, "next" is not collected. I assumed that "next" will be automatically collected by GC because "next" is no more referenced when "strong" is set to null. However, when "strong.next" is set to null, "next" is collected as we think. Why is "next" not collected automatically when strong is set to null?