1. 概要

この記事では、Java言語でのファントムリファレンスの概念を見ていきます。

2. ファントム参照

ファントム参照には、softおよびweak参照との2つの大きな違いがあります。

ファントム参照の指示対象を取得できません。APIを介して指示対象に直接アクセスすることはできません。そのため、このタイプの参照を処理するには参照キューが必要です。

ガベージコレクターは、その指示対象のfinalizeメソッドが実行された後、参照キューにファントム参照を追加します。 これは、インスタンスがまだメモリ内にあることを意味します。

3. ユースケース

それらが使用される2つの一般的なユースケースがあります。

最初の手法はで、オブジェクトがメモリからいつ削除されたかを判断します。これはメモリに依存するタスクのスケジュールに役立ちます。 たとえば、大きなオブジェクトが削除されるのを待ってから、別のオブジェクトをロードできます。

2番目の方法は、で、ファイナライズメソッドの使用を回避し、ファイナライズプロセスを改善します。

3.1. 例

次に、この種の参照がどのように機能するかを実際に理解するために、2番目のユースケースを実装しましょう。

まず、リソースをクリアするためのメソッドを定義するために、PhantomReferenceクラスのサブクラスが必要です。

public class LargeObjectFinalizer extends PhantomReference<Object> {

    public LargeObjectFinalizer(
      Object referent, ReferenceQueue<? super Object> q) {
        super(referent, q);
    }

    public void finalizeResources() {
        // free resources
        System.out.println("clearing ...");
    }
}

次に、強化されたきめ細かいファイナライズを記述します。

ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
List<LargeObjectFinalizer> references = new ArrayList<>();
List<Object> largeObjects = new ArrayList<>();

for (int i = 0; i < 10; ++i) {
    Object largeObject = new Object();
    largeObjects.add(largeObject);
    references.add(new LargeObjectFinalizer(largeObject, referenceQueue));
}

largeObjects = null;
System.gc();

Reference<?> referenceFromQueue;
for (PhantomReference<Object> reference : references) {
    System.out.println(reference.isEnqueued());
}

while ((referenceFromQueue = referenceQueue.poll()) != null) {
    ((LargeObjectFinalizer)referenceFromQueue).finalizeResources();
    referenceFromQueue.clear();
}

まず、必要なすべてのオブジェクトを初期化します。 referenceQueue –キューに入れられた参照を追跡するため、 references –後でクリーニング作業を実行するため、 largeObjects –を模倣するため大規模なデータ構造。

次に、ObjectクラスとLargeObjectFinalizerクラスを使用してこれらのオブジェクトを作成しています。

ガベージコレクターを呼び出す前に、 largeObjects リストを逆参照して、大量のデータを手動で解放します。 Runtime.getRuntime()。gc()ステートメントのショートカットを使用してガベージコレクターを呼び出したことに注意してください。

System.gc()がガベージコレクションをすぐにトリガーしないことを知っておくことが重要です。これは、JVMがプロセスをトリガーするための単なるヒントです。

for ループは、すべての参照がキューに入れられていることを確認する方法を示しています。参照ごとにtrueが出力されます。

最後に、 while ループを使用して、キューに入れられた参照をポーリングし、それぞれのクリーニング作業を実行しました。

4. 結論

このクイックチュートリアルでは、Javaのファントム参照を紹介しました。

これらが何であるか、そしてそれらがいくつかの単純で的確な例でどのように役立つかを学びました。