1. 概要

この簡単な記事では、Javaのソフト参照について説明します。

それらが何であるか、なぜそれらが必要なのか、そしてそれらを作成する方法を説明します。

2. ソフト参照とは何ですか?

ソフト参照オブジェクト(またはソフトに到達可能なオブジェクト)は、メモリ要求に応じてガベージコレクタによってクリアできます。 ソフトに到達可能なオブジェクトには、それを指す強い参照がありません

ガベージコレクターが呼び出されると、ヒープ内のすべての要素の反復が開始されます。 GCは、参照型オブジェクトを特別なキューに格納します。

ヒープ内のすべてのオブジェクトがチェックされた後、GCは、上記のキューからオブジェクトを削除することにより、削除する必要があるインスタンスを決定します。

これらのルールはJVMの実装ごとに異なりますが、ドキュメントには、ソフトに到達可能なオブジェクトへのすべてのソフト参照は、JVMがOutOfMemoryErrorをスローする前にクリアされることが保証されていると記載されています。

ただし、ソフト参照がクリアされる時間や、さまざまなオブジェクトへのそのような参照のセットがクリアされる順序は保証されません。

原則として、JVM実装は、最近作成された参照または最近使用された参照のいずれかのクリーニングを選択します。

ソフトに到達可能なオブジェクトは、最後に参照された後もしばらくの間存続します。 デフォルト値は、ヒープ内の空きメガバイトあたりのライフタイムの1秒です。 この値は、 -XX:SoftRefLRUPolicyMSPerMBフラグを使用して調整できます。

たとえば、値を2.5秒(2500ミリ秒)に変更するには、次を使用できます。

-XX:SoftRefLRUPolicyMSPerMB=2500

弱参照と比較すると、ソフト参照は、追加のメモリが必要になるまで存在し続けるため、寿命が長くなる可能性があります。

したがって、オブジェクトをできるだけ長くメモリに保持する必要がある場合は、これらの方が適しています。

3. ソフトリファレンスのユースケース

ソフト参照は、メモリ管理が非常に重要な要素であるメモリセンシティブキャッシュの実装に使用できます。

ソフト参照の指示対象が強く到達可能である限り、つまり、実際に使用されている限り、参照はクリアされません。

たとえば、キャッシュは、それらのエントリへの強力な指示対象を保持し、残りのエントリをガベージコレクタの裁量で破棄することにより、最近使用されたエントリが破棄されるのを防ぐことができます。

4. ソフト参照の操作

Javaでは、ソフト参照は java.lang.ref.SoftReferenceクラスで表されます。

初期化するには2つのオプションがあります。

最初の方法は、指示対象のみを渡すことです。

StringBuilder builder = new StringBuilder();
SoftReference<StringBuilder> reference1 = new SoftReference<>(builder);

2番目のオプションは、 java.lang.ref.ReferenceQueueへの参照と指示対象への参照を渡すことを意味します。 参照キューは、ガベージコレクターによって実行されたアクションを認識できるように設計されています。この参照の参照対象を削除することを決定すると、参照オブジェクトが参照キューに追加されます。

SoftReferenceReferenceQueue:で初期化する方法は次のとおりです。

ReferenceQueue<StringBuilder> referenceQueue = new ReferenceQueue<>();
SoftReference<StringBuilder> reference2
 = new SoftReference<>(builder, referenceQueue);

java .lang.ref.Reference として、参照対象を取得およびリセットするためのメソッドgetおよびclearがそれぞれ含まれています。

StringBuilder builder1 = reference2.get();
reference2.clear();
StringBuilder builder2 = reference2.get(); // null

この種の参照を処理するたびに、getによって返される参照が存在することを確認する必要があります。

StringBuilder builder3 = reference2.get();
if (builder3 != null) {
    // GC hasn't removed the instance yet
} else {
    // GC has cleared the instance
}

5. 結論

このチュートリアルでは、ソフト参照の概念とその使用例について理解しました。

また、プログラムで作成して操作する方法も学びました。