弱参照はガベージコレクターに翻弄されることを理解しており、弱参照が存在することを保証することはできません。弱参照の必要性はわかりませんでしたが、確かに理由があるはずです。
- Javaで弱参照が必要なのはなぜですか?
- Javaでの弱参照の実用的な(いくつかの)使用法は何ですか?あなたがあなたのプロジェクトでどのように使用したかを共有することができれば、それは素晴らしいことです!
弱参照はガベージコレクターに翻弄されることを理解しており、弱参照が存在することを保証することはできません。弱参照の必要性はわかりませんでしたが、確かに理由があるはずです。
弱いハッシュマップを使用することは、実際にはかなり頻繁に悪い考えです。一つには、間違えるのは簡単ですが、さらに悪いことに、それは通常、ある種のキャッシュを実装するために使用されます。
これが意味することは次のとおりです。プログラムはしばらくの間良好なパフォーマンスで正常に実行され、ストレスの下で、より多くのメモリを割り当て(より多くのリクエスト=より多くのメモリプレッシャー=おそらくより多くのキャッシュエントリ)、GCにつながります。
これで、システムに高いストレスがかかっているときに突然、GCを取得するだけでなく、最も必要なときにキャッシュ全体が失われます。この問題は面白くないので、少なくとも適度なサイズのハード参照LRUキャッシュを使用して、この問題を軽減する必要があります。その場合でも、weakrefを使用できますが、追加のヘルプとしてのみ使用できます。
その「バグ」に見舞われたプロジェクトを複数見たことがあります。
私が見た弱い参照の最も「明確に賢明な」使用法はStriped
、ロックストライピングを行うGuava'sです。基本的に、現在ロック変数への参照を保持しているスレッドがない場合、そのロックを維持する理由はありませんか?そのロックは過去に使用されていた可能性がありますが、現在は必要ありません。
どちらを使用するかについてルールを指定する必要がある場合、将来何かを使用する可能性がある場合はソフト参照が望ましいと思いますが、本当に必要な場合は再計算できます。参照がメモリ不足になった後、値が必要にならないことが確実な場合は、弱参照が特に適しています。(たとえばequals(Object)
、マップキータイプの特定の実装にデフォルトの参照等式を使用し、オブジェクトが他の場所で参照されなくなった場合、エントリが二度と参照されないようにすることができます。
弱参照を使用する主な理由は、WeakHashMapを介した間接的なものです。
オブジェクトのコレクションを(キャッシュとして、またはその他の理由で)マップに格納することもできますが、特にオブジェクトが比較的大きい場合は、マップが存在する限り、オブジェクトをメモリに保持しないでください。
WeakHashMapを使用すると、他の参照が存在しない場合はガベージコレクションされるため、オブジェクトをメモリに保持するのはマップからの参照だけではないことを確認できます。
オブジェクトが参照されている限り、いくつかの情報を保持する必要があるが、オブジェクトがいつなくなるかわからない場合は、弱参照を使用して情報を追跡できます。
はい、それは良い影響を及ぼします。
上記の「ウィジェットのシリアル番号」の問題の例では、組み込みのクラスを使用するのが最も簡単です
WeakHashMap
。キー(値ではありません!)が弱参照を使用して参照されることを除いて、とWeakHashMap
まったく同じように機能します。キーがガベージになると、そのエントリは自動的に削除されますHashMap
。これにより、私が説明した落とし穴を回避し、からへWeakHashMap
の切り替え以外の変更は必要ありません。インターフェイスを介してマップを参照するという標準的な規則に従っている場合は、他のコードで変更を認識する必要はありません。HashMap
WeakHashMap
Map
メモリリークに対する手段を確保するには、JVMプラットフォームに弱い参照オブジェクトが必要です。
Java開発者が知っておくべきことですが、Javaは予想以上にリークする可能性があります。このステートメントは、オブジェクトが使用されなくなったが、一部のコレクションがそのインスタンスを強く参照している場合に特に当てはまります。メモリリークの非常に単純ですが繰り返し発生する例であり、実際には、強力な参照が存在するまでメモリ領域の割り当てが解除されません。
上記の場合、コレクション内の弱参照オブジェクトは、次のことを保証します。強い参照チェーンがなくても、弱いチェーンしかない場合、インスタンスは収集可能なgarbaceとして選択できます。
私の意見では、Javaプラットフォームが提供するすべての機能はある程度有用です。非常に熟練したプログラマーは、C ++が非常に高品質のコードを記述しているので、Javaを高速で信頼性の高いものにすることができます。
Javaガベージコレクションを決定論的にする必要があります。(少し風刺的な観点から、いくつかの真実があります)。
AWeakReference
は、参照を保持している他のオブジェクトからオブジェクト自体を適切に削除せずに、オブジェクトをガベージコレクションに向かわせたい場合に適しています。
パブリッシュ/サブスクライブやイベントバスなどのシナリオでは、サブスクライブするオブジェクトへの参照のコレクションが保持されます。これらの参照は弱くする必要があります。これにより、サブスクライバーは、サブスクリプションを解除することなく、範囲外に簡単に移動できます。サブスクライバーは、アプリ内の他のすべての場所が強力な参照をリリースした後、「消える」ことができます。その時点で、サブスクリプションリストまたはイベントバスがサブスクライバーに接続し続ける必要はありません。を使用するとWeakReference
、オブジェクトは忘却の途中で続行できます。
サブスクライブしているオブジェクトは、知らないうちにサブスクライブされているか、他のサードパーティオブジェクトによってpub-subまたはイベントバスにサブスクライブされている可能性があります。サブスクライバーのライフサイクルの後半でサブスクリプションを解除するための呼び出しを調整することは、非常に面倒な場合があります。したがって、正式にサブスクライブを解除せずにサブスクライバーをフェードアウトさせると、コードが大幅に簡素化され、サブスクライブ解除の調整が失敗した場合の難しいバグを回避できます。
この回答とこの回答に見られるように、スレッドセーフな弱参照のセットの例を次に示します。
this.subscribersSet =
Collections.synchronizedSet(
Collections.newSetFromMap(
new WeakHashMap <>()
)
);
上記のリンクされた回答で説明されているように、セット内のエントリは、ガベージコレクションが実際に実行されるまで実際には削除されないことに注意してください。ガベージコレクションの候補として存在している間(どこにも強力な参照が残っていない)、アイテムはセットに残ります。