0

ファントム参照の使用法に少し混乱しています。ファントム参照のみを指しているオブジェクトは、ガベージコレクターが好きなときにいつでも収集できると読みました。しかし、私の例では意図したとおりに機能していません。

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");
}  

両方のシナリオで動作が異なるのはなぜですか?

4

1 に答える 1

2

ファントム参照は通常の Java オブジェクトであり、到達できない場合はガベージ コレクトされます。

ファントム参照が、参照されるオブジェクトの前または同じコレクションで収集された場合、参照キューに追加されません。

すべてのファントム参照をコレクションに配置すると、参照が時期尚早にガベージ コレクションされるのを防ぐことができます。

通常、未処理のファントム参照の専用コレクションと、参照キューが必要です。

ファントム リファレンス ベースのポスト モーテム クリーンアップの実装例については、この記事を参照してください。

于 2016-12-11T19:37:26.537 に答える