ファントム参照の使用法に少し混乱しています。ファントム参照のみを指しているオブジェクトは、ガベージコレクターが好きなときにいつでも収集できると読みました。しかし、私の例では意図したとおりに機能していません。
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に割り当てられると、オブジェクトが自動的にガベージコレクションされると思っていました。不思議なことに、レジスタ関数で次の行のコメントを外した場合にのみ、ガベージ コレクションが実行されます。
//cleanUpMap.put(pref, "Free up resources");"
その背後にある理由は何ですか?しかし、Main 関数自体にファントム参照を作成すれば、この問題は発生しません。つまり、次のコードのように、メイン関数内で null に「strong」が割り当てられている場合、オブジェクトは自動的にガベージ コレクションされます。
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");
}
両方のシナリオで動作が異なるのはなぜですか?