SoftReference

Java NetBeans

あけましておめでとうございます。

とうとう今年の5月で平成が終わってしまいます。

新しい元号がまだ発表されてないので一部の人は困っているようですがどうにかならないものなんでしょうか?

さて、どうにもならないことをどうかしようとすると頭が痛くなるから現実逃避のために Java で遊ぶとしよう。

SoftReference って聞いたことはあるけど実際にプログラムを組む上で使った記憶がないのでこれで遊んでみよう。

java.base モジュールの java.lang.ref パッケージにある public class SoftReference<T> extends Reference<T> クラスです。

API ドキュメントには下記のように記されてます。

メモリー要求に応じてガベージ・コレクタの判断でクリアされるソフト参照オブジェクトです。

ソフト参照は通常、メモリー・センシティブなキャッシュを実装するために使用されます。

ある時点で、オブジェクトがソフト到達可能であると、ガベージ・コレクタが判断したとします。

その時点で、ガベージ・コレクタは、そのオブジェクトへのソフト参照すべてと、強参照のチェーンを経由してそのオブジェクトに到達できるような、ソフト到達可能なほかのオブジェクトへのソフト参照すべてを原子的にクリアすることを選択できます。

同時にまたはあとで、ガベージ・コレクタは、参照キューに登録されているそれらの新しくクリアされたソフト参照をキューに入れます。

ソフト到達可能なオブジェクトへのすべてのソフト参照は、仮想マシンがOutOfMemoryErrorをスローする前にクリアされていることが保証されています。

そうでない場合、ソフト参照がクリアされる時点、またはさまざまなオブジェクトへの一連のソフト参照がクリアされる順序に制約はありません。

ただし、仮想マシンの実装は、最近作成されたソフト参照または最近使用されたソフト参照をクリアしないことが奨励されます。

このクラスの直接のインスタンスは、単純なキャッシュを実装するために使用できます。

このクラスまたは派生したサブクラスは、より洗練されたキャッシュを実装するために、もっと大きなデータ構造でも使用できます。

ソフト参照のリファレントが強到達可能であるかぎり、つまり実際に使用されているかぎり、ソフト参照はクリアされません。

このため、たとえば洗練されたキャッシュは、エントリへの強いリファレントを維持することで、もっとも新しく使用されたエントリが破棄されることを防ぎ、ほかのエントリはガベージ・コレクタの判断で破棄されるようにできます。

つまり、ガベージ・コレクタが参照の使用頻度とヒープの状態をみて参照の解放を勝手にやってくれるので OutOfMemoryError でプログラムが止まってしまうことがない。

ガベージ・コレクタが必死でがんばってくれる!私は感謝するぞ!

で、この SoftReference<T> クラスにはコンストラクタが2種類あります。

SoftReference​(T referent)

指定されたオブジェクトを参照する新しいソフト参照を作成します。新しい参照は、どのキューにも登録されません。

パラメータ:referent – 新しいソフト参照が参照するオブジェクト

SoftReference​(T referent, ReferenceQueue<? super T> q)

指定されたオブジェクトを参照し、指定されたキューに登録されている新しいソフト参照を作成します。

パラメータ:referent – 新しいソフト参照が参照するオブジェクトq – 参照が登録されるキュー。登録が必要ない場合はnull

メソッドは一つだけあります。

public T get()

参照オブジェクトのリファレントを返します。 プログラムまたはガベージ・コレクタによって、この参照オブジェクトがすでにクリアされている場合、このメソッドはnullを返します。

戻り値:この参照が表すオブジェクト。この参照オブジェクトがクリアされている場合はnull

もの凄く質素なクラスですね。

そう言うことでさっそくお試しプログラムを組んでみました。

 

 

無駄にメモリーを消費するインスタンスを1000個作っているだけです。

普通なら OutOfMemoryError でプログラムが止まってしまうはずですが SoftReference を使って賢いガベージ・コレクタの力で完走させようというものです。

プログラムの実行結果は次のようになりました。

Windows 10 10.0 amd64
JDK 11.0.1

UsedMemory: 113246208   G1 Young Generation   GC Count: 0   GCTime = 0     G1 Old Generation   GC Count: 0   GCTime = 0    
UsedMemory: 222298112   G1 Young Generation   GC Count: 0   GCTime = 0     G1 Old Generation   GC Count: 0   GCTime = 0    
UsedMemory: 331350016   G1 Young Generation   GC Count: 0   GCTime = 0     G1 Old Generation   GC Count: 0   GCTime = 0    
UsedMemory: 440401920   G1 Young Generation   GC Count: 0   GCTime = 0     G1 Old Generation   GC Count: 0   GCTime = 0    
UsedMemory: 546493104   G1 Young Generation   GC Count: 1   GCTime = 3     G1 Old Generation   GC Count: 0   GCTime = 0

UsedMemory: 110148312   G1 Young Generation   GC Count: 57   GCTime = 109     G1 Old Generation   GC Count: 2   GCTime = 1808    
    — POLL:java.lang.ref.SoftReference@59fa1d9b —
    — POLL:java.lang.ref.SoftReference@28d25987 —

    — POLL:java.lang.ref.SoftReference@527740a2 —
    — POLL:java.lang.ref.SoftReference@13a5fe33 —
UsedMemory: 219243560   G1 Young Generation   GC Count: 58   GCTime = 110     G1 Old Generation   GC Count: 2   GCTime = 1808    
UsedMemory: 328295464   G1 Young Generation   GC Count: 58   GCTime = 110     G1 Old Generation   GC Count: 2   GCTime = 1808 

UsedMemory: 6762364184   G1 Young Generation   GC Count: 222   GCTime = 332     G1 Old Generation   GC Count: 12   GCTime = 8964    
UsedMemory: 6871416088   G1 Young Generation   GC Count: 222   GCTime = 332     G1 Old Generation   GC Count: 12   GCTime = 8964

プログラムが終了するまで1分8秒もかかった。

私の7年前のパソコンが壊れたのかと思ってしまった。(^_^;)

NetBeans のプロファイラでどんなかんじなのか確認してみました。

1

 

2

 

3

 

確かに OutOfMemoryError でプログラムが止まらないようにガベージ・コレクタが頑張っているようだけどGC時間長くない?

プログラムの実行結果からも気のせいか GC の回数、累積時間が長いような気がする。

SoftReference ってこんなものなのかなぁ・・・

あっ、なにかプログラムに問題があるのかもしれない。

これは WeakReference で試して比較してみるしかない。

ということで次回に続く

Hatena タグ: ,

« »

Comment

Trackback

  1. […] http://yucchi.jp/blog/?p=2675 […]

  2. […] その前に前回、前々回と PhantomReference の兄弟の SoftReference と WeakReference の御浚いをしておきましょう。 […]

Leave a Reply

* が付いている項目は、必須項目です!

次の HTML タグと属性を利用できます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

*

Trackback URL