2012-02-06 5 views
7

Javadocsは、「キーが破棄されると、そのエントリはであり、実際にはがマップから削除されました」と述べています。WeakHashMapと強く参照される値

ただし、このようなMap.Entryエントリを時々削除するスレッドがない場合、値オブジェクトはマップによって強く参照されませんか?しかし、そのようなスレッドは実行されていないので、メソッド呼び出しだけで、そのようなエントリを一度に1つずつ削除できます。

ほとんどの場合、その理由としてWeakHashMap<K, WeakReference<V>>を使用します。なぜ彼らはそれをデフォルトの振る舞いにしていないでしょうか?

+0

http://stackoverflow.com/questions/2473410/question-about-weakhashmapはほぼ同じ質問です。しかし私は自分の主張が正しかったかどうかを知りたがっています.get()は、キーがgc'edされたことを発見したときにのみ削除されますが、WeakReferencesを値として使用しない限り、 –

+0

ええ、ちょうど投票されました。別のものが必要な場合は、独自のバージョンを作成してください。 –

+2

何か別のものが必要な場合は、図書館を使用してください。 Guavaには、MapMakerがあり、キーと値の参照の強さを設定できます:http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/MapMaker html –

答えて

8

参照キューは、エントリを自動的に削除するために使用されます。適切な到達性の変化が検出された後、参照オブジェクトはガベージコレクタによって付加され登録される

http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/ref/ReferenceQueue.html

参照キュー。

は基本的に、弱参照は、ガベージコレクタのコア部分であるので、GC掃引が発生した場合、未使用参照が見出され、キューに入れ、作用はこれらのキューの内容に基づいて取り出すことができるされています。

スレッドは、キューのremoveメソッドに置かれ、クリーンアップが必要なときに警告されるか、pollキューに置かれます。

"Java theory and practice: Plugging memory leaks with weak references"は説明:

WeakHashMapの実装では、弱参照と共通のイディオムを示す - いくつかの内部オブジェクトはWeakReferenceに延びています。

...

WeakHashMapは、彼らがもはやアプリケーションによって使用されている場合、キーのオブジェクトがガベージコレクトすることができなかった、マップキーを保持するための弱い参照を使用し、get()実装は、からのライブのマッピングを伝えることができます死んだものはWeakReference.get()の返信でnullです。しかしこれは、アプリケーションの存続期間中、Mapのメモリ消費量が増加しないようにするために必要な量の半分に過ぎません。キーオブジェクトが収集された後、マップからデッドエントリを削除するために何かを行う必要があります。 それ以外の場合、マップは単にデッドキーに対応するエントリでいっぱいになります。これはアプリケーションには見えませんが、キーがあってもMap.Entryオブジェクトと値オブジェクトは収集されないため、アプリケーションのメモリが不足する可能性があります。

...

リファレンス・キューは、オブジェクトのライフサイクルについてアプリケーションに情報をフィードバックするガベージコレクタの主要な手段です。弱い参照には2つのコンストラクタがあります.1つは引数として参照のみを取り、もう1つは参照キューを取ります。関連する参照キューで弱参照が作成され、参照先がGCの候補になると、参照オブジェクトが消去された後に、参照オブジェクトではない参照オブジェクトが参照キューにエンキューされます。アプリケーションは参照キューから参照を取得し、参照先が収集されたことを知ることで、弱いコレクションから外れたオブジェクトのエントリを削除するなど、関連するクリーンアップアクティビティを実行できます。 (参考キューはBlockingQueueのと同じデキューのモードを提供 - ポーリング、時限ブロッキング、およびアンタイムドのブロッキング。)

EDIT:

でもキューと、弱いマップはまだ漏れることができます。 Ephemeronsは、弱いキーがキーを参照する強く保持された値を参照する場合を解決しようとする試みです。それらはjavaで実装できません。

エフェメロンは、レジストリを使用してオブジェクトにプロパティを「アタッチ」しようとするときによく見られる問題を解決します。いくつかのプロパティをオブジェクトに関連付ける必要がある場合、このオブジェクトのインスタンス変数に(GCの動作に関して)プロパティのライフタイムが存在する必要があります。ここ

property --------- registry --------- association --------- object 

は、レジストリ(第三者)(レジストリから手動で除去することを必要とするであろうアソシエーション自体の上に保持する。しかし、これは、オブジェクトなどとしての特性と外部の関連性を有することによって複雑になります自動ガベージコレクションの代わりに)。この問題は、さまざまな弱い関連タイプのうちの1つを使用することによって、特定の具体的な状況で常に解決できますが、「正しい」種類の関連付けを選択することは、いくつかのものが動的に変化する可能性のあるさまざまな要因によって決まります。

エフェメロンは、エフェメロンの '内容'(値)がキーがガベージコレクションされるまで強く保持されることを定義することによってこの問題を解決します。その後、エフェメロンの内容は弱く保持されます。したがって、エフェメロンの内容は、ガベージコレクションの対象となることができます。ガベージコレクションの対象となるのは、オブジェクトのインスタンス変数で観測される正確な動作であるガベージコレクション可能な場合のみです。

+0

参照キューが独自のフックを呼び出すことができません。 –

+0

あなたのリンクから "WeakHashMapには、ほとんどのマップ操作中に呼び出されるexpungeStaleEntries()というプライベートメソッドがあります。"有用である。実際に参照キューで読み取りをブロックするスレッドを生成する方が良いアイデアかもしれません。 GuavaのMapMakerはそうかもしれません。 –

+1

@ UstamanSangat、私はMapMakerが何をしているのかわかりませんが、expungeStaleEntries()は参照キューをポーリングして、マップを使ってクリーンアップを償却します。 MapMakerのようなものを使って自分のキークリーニングを実装しようとする前に、私は試みます。Btw、弱いキーマップを使用してもメモリをリークできる方法を指摘する編集を追加しました。 –

関連する問題