Javaのソフトリファレンス

Javaのソフト参照

1. 概要

この簡単な記事では、Javaのソフトリファレンスについて説明します。

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

2. ソフトリファレンスとは何ですか?

ソフト参照オブジェクト(またはソフト到達可能オブジェクト)は、メモリ要求に応じてガベージコレクターによってクリアできます。 A softly reachable object has no strong references pointing to it

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

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

これらのルールはJVMの実装ごとに異なりますが、ドキュメントにはall soft references to softly-reachable objects are guaranteed to be cleared before a JVM throws an OutOfMemoryError.と記載されています。

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

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

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

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

-XX:SoftRefLRUPolicyMSPerMB=2500

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

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

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

Soft references can be used for implementing memory-sensitive cachesここで、メモリ管理は非常に重要な要素です。

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

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

4. ソフトリファレンスの操作

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

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

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

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

2番目のオプションは、java.lang.ref.ReferenceQueueへの参照と指示対象への参照を渡すことを意味します。 Reference queues are designed for making us aware of actions performed by the Garbage Collector.この参照の指示対象を削除することを決定すると、参照オブジェクトを参照キューに追加します。

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

ReferenceQueue referenceQueue = new ReferenceQueue<>();
SoftReference 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. 結論

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

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