Javaによるキャッシュの実装Tips

HashMapを使ったキャッシュの問題点

  • 削除ロジックを入れなければOutOfMemoryErrorの原因となる
  • どれくらいの量が適切か判断が難しい
  • 古いキャッシュを効率的に捨てるロジックを実装するのはけっこう面倒

解決策

メモリが足りなくなるとエントリが自動的にガベージコレクションされるMapがあれば良い。
GCの対象を制御できるとなお良い。

Java言語仕様: オブジェクト参照の種類

  • Strong Reference - 強参照。普通の参照。ガベージコレクタがこの参照で到達できるオブジェクトはGCされない。
  • Weak Reference - 弱参照。この参照のみで到達できるオブジェクトはGCされる。
  • Soft Reference - ソフト参照。この参照のみで到達できるオブジェクトは、ヒープメモリ残量に応じてGCされる。
  • Phantom Reference - ファントム参照。この参照のみで到達できるオブジェクトは、finalize()が呼ばれた後も、参照が明示的にクリアされるまでGCされない。

キャッシュ用途にはソフト参照が最適。

WeakHashMap

標準ライブラリにある。
キーを弱参照で保持し、GCによるキー削除に応じてエントリをマッピングから削除するらしい。
GCが起こると必ずエントリが一掃されるので、ライフタイムが短いオブジェクトの一時保存向き。

SoftHashMap

あっても良さそうだが標準ライブラリにない。(sun.misc.SoftCacheがあるが非公開API
誰か作ってないかな。

あった。


Implementing a SoftReference-based HashMap
http://archive.devx.com/java/free/articles/Kabutz01/Kabutz01-1.asp
ソースコード
http://archive.devx.com/java/free/articles/Kabutz01/Kabutz01-2.asp


オブジェクトをHashMapにソフト参照で保持するので、残りヒープメモリが少なくなったらGCされる。
最近使ったオブジェクトはLinkedListに強参照で保持するので、GCの対象外になる。
LinkedListのサイズはコンストラクタ引数で指定できる。


短いソースなので、理解するのも容易。