回答:
Javaは、二つの異なるタイプ/クラス提供して参照オブジェクト:強いと弱いです。弱参照オブジェクトは、さらにソフトとファントムに分類できます。
ポイントごとに行きましょう。
強い参照オブジェクト
StringBuilder builder = new StringBuilder();
別に指定されていない場合、これは参照オブジェクトのデフォルトのタイプ/クラスですbuilder
。強力な参照オブジェクトです。この種類の参照は、参照されるオブジェクトをGCに適格にしません。つまり、強い参照オブジェクトのチェーンによってオブジェクトが参照されると、そのオブジェクトはガベージコレクションされません。
弱い参照オブジェクト
WeakReference<StringBuilder> weakBuilder = new WeakReference<StringBuilder>(builder);
弱参照オブジェクトは、参照オブジェクトのデフォルトのタイプ/クラスではないため、上記の例のように、明示的に指定する必要があります。この種類の参照により、参照オブジェクトがGCに適格になります。つまりStringBuilder
、メモリ内のオブジェクトに到達できる唯一の参照が実際には弱い参照である場合、GCはStringBuilder
オブジェクトのガベージコレクションを実行できます。メモリ内のオブジェクトが弱参照オブジェクトのみによって到達可能である場合、そのオブジェクトは自動的にGCの対象になります。
弱さのレベル
ソフトとファントムの 2つの異なるレベルの弱点を登録できます。
ソフト参照オブジェクトがそのメモリ内に残り、もう少し基本的に弱参照オブジェクトである:利用可能なメモリがないとのリスクがあるまで、通常は、GCサイクルに耐えるOutOfMemoryError
(その場合、それを除去することができるが)。
一方、ファントム参照オブジェクトがオブジェクトのみが効果的にメモリから削除されましたを正確に知っておくと便利です:通常、それらが固定するために使用されている奇妙なファイナライズ()復活/復活の行動を、彼らは実際にはオブジェクト自身を返しませんので、しかし、彼らの記憶の存在を追跡するのを助けるだけです。
弱参照オブジェクトは、キャッシュモジュールの実装に最適です。実際、強い参照チェーンからオブジェクト/値に到達できなくなった場合に、GCがメモリ領域をクリーンアップできるようにすることで、一種の自動エビクションを実装できます。例は、弱いキーを保持するWeakHashMapです。
弱い参照:
簡単に言うと、弱い参照とは、オブジェクトをメモリに残しておくのに十分な強さではない参照です。弱い参照を使用すると、ガベージコレクターの機能を利用して到達可能性を判断できるため、自分で行う必要はありません。
ソフトリファレンス:
ソフト参照は弱参照とまったく同じですが、参照先のオブジェクトを捨てたくないという点が異なります。到達可能性が低いオブジェクト(オブジェクトへの最も強い参照はWeakReferencesです)は、次のガベージコレクションサイクルで破棄されますが、到達可能性が低いオブジェクトは、通常しばらくの間留まります。
ファントム参照:
ファントム参照は、SoftReferenceまたはWeakReferenceとはかなり異なります。オブジェクトのグリップが非常に弱いため、オブジェクトを取得することもできません。get()メソッドは常にnullを返します。そのような参照の唯一の用途は、それがReferenceQueueにエンキューされたときを追跡することです。その時点で、参照先のオブジェクトが死んでいることがわかります。
このテキストは、https://weblogs.java.net/blog/2006/05/04/understanding-weak-referencesから抽出されました
との単純な違いはSoftReference
、Android DeveloperWeakReference
によって提供されます。
a SoftReference
とa の違いはWeakReference
、参照をクリアしてエンキューすることを決定する時点です。
A SoftReference
は、できるだけ遅く、つまりVMがメモリ不足になる危険性がある場合に備えて、クリアしてエンキューする必要があります。
WeakReference
弱参照であることが判明するとすぐに、A をクリアしてキューに入れることができます。
使用した3つの用語は、主にガベージコレクションを取得するObjectの資格に関連しています。
弱い参照 ::その参照は、オブジェクトをメモリに残すのを強制するほど強くはありません。そのオブジェクトをガベージコレクションのために収集するガベージコレクターの気まぐれです。 そのGCに強制的に収集させないようにすることはできません。
ソフトリファレンス ::弱リファレンスとほぼ同じです。しかし、ガベージコレクションからの弱い参照よりもオブジェクトを少し強く保持していると言えます。
ガベージコレクターが最初のライフサイクル自体で弱い参照を収集する場合、ガベージコレクションの次のサイクルで弱い参照を収集します。
強い参照 ::上記の2種類の参照とは正反対です。ガベージコレクションを取得することはあまりありません(ほとんどの場合、収集されることはありません)。
詳細については、次のリンクを参照してください。
http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/ref/Reference.html
この記事は、強い参照、弱い参照、弱い参照、および幻の参照を理解するのに非常に役立ちます。
要約すると、
強い参照がある場合オブジェクトへの、そのオブジェクトはGC(ガベージコレクタ)によって回収/収集することはできません。
弱い参照しかない場合オブジェクトへのある場合(強い参照がない場合)、オブジェクトは次のGCサイクルでGCによって再利用されます。
オブジェクトへのソフト参照のみ(強い参照なし)がある場合、オブジェクトは、JVMがメモリを使い果たしたときにのみ、GCによって再利用されます。
オブジェクトへのファントム参照を作成して、オブジェクトがにエンキューされるタイミングを追跡しますReferenceQueue
。きめ細かいファイナライズを実行できることがわかったら、(これにより、ファントム参照では参照元が提供されないため、オブジェクトを誤って復活させることがなくなります)。この記事を読んで、これに関する詳細を確認することをお勧めします。
つまり、強い参照には究極の力がありますがあります(GCで収集することはできません)。
ソフト参照は弱い参照よりも強力です(JVMがメモリ不足になるまでGCサイクルを回避できるため)。
弱い参照は、ソフト参照よりも強力ではありません(オブジェクトが他の強い参照を持たない場合は、GCサイクルをエスケープできず、再利用されるため)。
レストランのアナロジー
これで、強い顧客(強い参照に類似)であれば、新しい顧客がレストランに来た場合でも、何が起こっても、テーブル(ヒープのメモリ領域)を離れることはありません。ウェイターはあなたにレストランを去るように言う(またはあなたに要求する)権利はない。
あなたがいる場合には、ソフトの顧客(ソフト参照に類似した)新しい顧客はレストランに来た場合、その後、ウェイターが新しい顧客を収容するために残された他の空のテーブルが存在しない場合を除き、テーブルを残すように頼むことはありません。(言い換えれば、ウェイターは、新しい顧客が参加し、この新しい顧客のために残っている他のテーブルがない場合にのみ、テーブルを離れるように求めます)
あなたが弱い顧客(弱い参照に類似)である場合、ウェイターは彼の意志で(いつでも)レストランを出るように頼むことができます:P
4度の参照- Strong, Weak, Soft, Phantom
強い-一種の参照であり、参照されるオブジェクトをGCに適格にしません。ビルダークラス。例-StringBuilder
弱い-GCの対象となるリファレンスです。
Soft-メモリが使用可能になるまでオブジェクトがGCに適格な一種の参照です。画像キャッシュに最適です。メモリが使用可能になるまで保持されます。
ファントム-GCに直接適格なオブジェクトを持つ一種の参照です。オブジェクトがメモリから削除されたときを知るためにのみ使用されます。
使用:
オブジェクトがメモリから正確に削除された時期を特定できます。
とき
finalize()
メソッドがオーバーロードされ、その後、GCは、2つのクラスのGC対象とするオブジェクトのためにタイムリーに行われない場合があります。したがって、ファントム参照により、それらはGC beforeの対象になります。これが、ヒープの大部分がガベージである場合でもOutOfMemoryErrorsfinalize()
を取得できる理由です。
弱い参照は、キャッシュモジュールを実装するのに理想的です。
これらは、毎日コーディングする通常のオブジェクト参照です。
Employee emp = new Employee();
変数「emp」はEmployeeオブジェクトへの強い参照を保持します。強い参照のチェーンを介して到達可能なオブジェクトは、ガベージコレクションの対象となりません。通常、これは必要なことですが、常にそうであるとは限りません。ここで、コレクションまたはマップのデータベースから多くの従業員をフェッチしていて、定期的に多くの処理を実行する必要があるとします。したがって、パフォーマンスを維持するために、それらをキャッシュに保持します。
これは問題ありませんが、今は別のデータが必要で、それらのEmployeeオブジェクトは必要ありません。これらは、キャッシュ以外のどこからも参照されません。これらのオブジェクトは使用されていないがガベージコレクションの対象ではないため、メモリリークを引き起こしているのはどれですか。また、それらへの参照がないため、これらのオブジェクトをキャッシュから削除できません。したがって、ここでは手動でキャッシュ全体を空にする必要があります。これは退屈な作業ですが、他の種類の参照、たとえば弱い参照を使用することもできます。
弱い参照はオブジェクトをメモリに固定せず、他の参照から参照されない場合、次のGCサイクルでGCされます。Javaが提供するWeakReferenceクラスを使用して、上記の種類のキャッシュを作成できます。これは、他の場所から参照されていないオブジェクトを格納しません。
WeakReference<Cache> cache = new WeakReference<Cache>(data);
データにアクセスするには、cache.get()を呼び出す必要があります。弱い参照がガベージコレクションされた場合、getのこの呼び出しはnullを返す場合があります。NPEを回避するために戻り値を確認する必要があります。Javaは、弱参照を使用するコレクションを提供します。たとえば、WeakHashMapクラスは、キー(値ではなく)を弱参照として格納します。キーがGCされている場合、値も自動的にマップから削除されます。
弱参照もオブジェクトであるため、それらをクリーンアップする方法が必要です(参照しているオブジェクトがGCされている場合、それらはもはや役に立ちません)。弱い参照のReferenceQueueをコンストラクターに渡すと、ガベージコレクターは、その弱い参照をファイナライズまたはGCする前にReferenceQueueに追加します。このキューを定期的に処理して、デッドリファレンスを処理できます。
SoftReferenceはWeakReferenceに似ていますが、ガベージコレクションされる可能性は低くなります。ソフトリファレンスは、メモリの要求に応じて、ガベージコレクターの裁量でクリアされます。仮想マシンは、OutOfMemoryErrorをスローする前に、ソフト到達可能なオブジェクトへのすべてのソフト参照がクリアされることを保証します。
ファントム参照はすべての参照タイプの中で最も弱いため、それらに対してgetを呼び出すと常にnullが返されます。オブジェクトは、ファイナライズされた後、割り当てられたメモリが解放される前にファントムに参照されます。ファイナライズされる前にエンキューされる弱い参照とは対照的です。または、GC化されたファントム参照はほとんど使用されません。
では、それらはどのように役立つのでしょうか。ファントム参照を作成するときは、常にReferenceQueueを渡す必要があります。これは、ファントム参照を使用して、オブジェクトがいつGCされるかを確認できることを示しています。
ねえ、それで、ファイナライズと見なされてもまだGCされていないときに弱い参照がエンキューされた場合、ファイナライザブロック内のオブジェクトへの新しい強い参照を作成して、オブジェクトがGCされないようにすることができます。はい、できますが、おそらくこれを行うべきではありません。このケースをチェックするには、ファントム参照によってのみ到達可能なオブジェクトでない限り、GCサイクルは各オブジェクトに対して少なくとも2回発生します。これが、メモリに大量のゴミが含まれている場合でも、ヒープが不足する可能性がある理由です。ファントム参照はこれを防ぐことができます。
詳細については、私の記事「Javaでの参照のタイプ(ストロング、ソフト、ウィーク、ファントム)」を参照してください。