1概要

この記事では、Phantom Referenceの概念をJava言語で説明します。

** 2ファントム参考文献

ファントム参照は

soft



weak

の2つの大きな違いがあります。

ファントム参照の参照先を取得することはできません。参照先にはAPIから直接アクセスできないため、このような参照を処理するために参照キューが必要になります。

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


3ユースケース

一般的な用途は2つあります。

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

2番目の方法は、

finalize

メソッドの使用を避け、


ファイナライズ処理** を改善することです。


3.1. 例

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

まず、https://docs.oracle.com/javase/9​​/docs/api/java/lang/ref/PhantomReference.html[

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のファントムリファレンスを紹介しました。

私たちは、これらが何であるか、そしてそれらがいくつかの簡単でポイントに近い例でどのように役立つことができるかを学びました。