web-dev-qa-db-ja.com

Java:強参照/弱参照/弱参照/ファントム参照の違い

トピックについて この記事 を読んだことがありますが、実際には理解していません。概念を説明する際に、例とともにいくつかのアドバイスをお願いします。

162
user1204873

Javaは、参照オブジェクトの2つの異なるタイプ/クラスを提供します:strongおよびweak。弱い参照オブジェクトは、softphantomにさらに分割できます。ポイントごとに行きましょう。

強い参照オブジェクト

StringBuilder builder = new StringBuilder();

これは、特に指定しない限り、参照オブジェクトのデフォルトのタイプ/クラスです:builderは強力な参照オブジェクトです。この種の参照により、参照されるオブジェクトはGCに適格ではなくなります。つまり、オブジェクトが強力な参照オブジェクトのチェーンによって参照される場合は常に、ガベージコレクションできません。

弱い参照オブジェクト

WeakReference<StringBuilder> weakBuilder = new WeakReference<StringBuilder>(builder);

弱い参照オブジェクトは、参照オブジェクトのデフォルトのタイプ/クラスではないため、上記の例のように明示的に指定する必要があります。この種類の参照は、参照オブジェクトをGCに適格にします。つまり、メモリ内のStringBuilderオブジェクトに到達可能な唯一の参照が実際には弱い参照である場合、GCはStringBuilderオブジェクトのガベージコレクションを許可されます。メモリ内のオブジェクトが弱い参照オブジェクトによってのみ到達可能な場合、そのオブジェクトは自動的にGCの対象になります。

弱さのレベル

2つの異なるレベルの脆弱性を登録できます:softおよびphantom

soft参照オブジェクトは、基本的にはもう少しメモリに残る弱い参照オブジェクトです。通常、メモリが利用可能になるまでGCサイクルに抵抗し、OutOfMemoryErrorのリスクはありません(その点でケース、それは削除することができます)。

一方、phantom参照オブジェクトは、オブジェクトがメモリから効果的に削除された正確なタイミングを知るためにのみ有用です:通常、それらは修正に使用されます奇妙なfinalize()の復活/復活の振る舞い。実際にはオブジェクト自体を返さず、 メモリの存在を追跡する を助けるだけだからです。

弱い参照オブジェクトは、キャッシュモジュールの実装に最適です。実際、オブジェクト/値が強参照チェーンによって到達できなくなったときにGCがメモリ領域をクリーンアップできるようにすることで、一種の自動追い出しを実装できます。例は WeakHashMap 弱いキーの保持です。

129
Paolo Maresca

弱い参照:

簡単に言えば、弱い参照とは、オブジェクトを強制的にメモリに保持するのに十分なほど強力ではない参照です。弱い参照を使用すると、ガベージコレクターの機能を利用して到達可能性を判断できるため、自分で行う必要はありません。

ソフトリファレンス:

ソフト参照は、参照先のオブジェクトを捨てたくないということを除けば、弱い参照とまったく同じです。弱くしか到達できないオブジェクト(それに対する最強の参照はWeakReferences)は、次のガベージコレクションサイクルで破棄されますが、弱く到達可能なオブジェクトは一般にしばらく滞留します。

ファントムリファレンス:

ファントム参照は、SoftReferenceまたはWeakReferenceとはまったく異なります。そのオブジェクトに対するグリップは非常に弱く、オブジェクトを取得することさえできません。そのget()メソッドは常にnullを返します。このような参照の唯一の用途は、参照先のオブジェクトが死んでいることがわかっているため、ReferenceQueueにエンキューされるタイミングを追跡することです。

このテキストは以下から抽出されました: https://weblogs.Java.net/blog/2006/05/04/understanding-weak-references

72
Punith Raj

SoftReferenceWeakReferenceの単純な違いは、 Android Developer によって提供されます。

SoftReferenceWeakReferenceの違いは、参照をクリアしてエンキューする決定が下される時点です。

  • SoftReferenceは、できるだけ遅く、つまりVMがメモリ不足になる危険がある場合に、クリアしてキューに入れる必要があります。

  • WeakReferenceは、弱参照であることがわかっているとすぐにクリアされ、キューに入れられます。

23

使用した3つの用語は、主にObjectがGarbageを収集する資格に関連しています。

弱い参照::その参照は、オブジェクトをメモリ内に強制的に保持するほど強くはありません。そのガベージコレクターの気まぐれは、ガベージコレクションのためにそのオブジェクトを収集します。 そのGCがそれを収集しないように強制することはできません

ソフト参照::弱参照とほぼ同じです。しかし、ガベージコレクションからの弱い参照よりもオブジェクトを少し強く保持していると言えます。

ガベージコレクタが最初のライフサイクル自体で弱参照を収集する場合、ガベージコレクションの次のサイクルでソフト参照を収集します。

強い参照::上記の2種類の参照とは正反対です。ガベージコレクションを取得することはあまりありません(ほとんど収集されません)。

詳細については、次のリンクを参照してください。

http://docs.Oracle.com/javase/1.4.2/docs/api/Java/lang/ref/Reference.html

16
Sabya

4度の参照-Strong, Weak, Soft, Phantom

Strong-一種の参照であり、参照されるオブジェクトをGCに適格にしません。ビルダークラス。例-StringBuilder

弱い-GCに適格な参照です。

ソフト-メモリーが使用可能になるまでオブジェクトがGCに適格である一種の参照です。画像キャッシュに最適です。メモリが使用可能になるまで、それらを保持します。

Phantom-オブジェクトがGCに直接適格である一種の参照です。オブジェクトがメモリからいつ削除されるかを知るためだけに使用されます。

使用:

  1. オブジェクトがメモリから正確に削除されたときを識別できます。

  2. finalize()メソッドがオーバーロードされると、2つのクラスのGC適格オブジェクトに対してGCがタイムリーに発生しない場合があります。したがって、ファントム参照により、finalize()の前にGCに適格となるため、ほとんどのヒープがガベージであっても OutOfMemoryErrors を取得できます。

弱い参照は、キャッシュモジュールを実装するのに理想的です。

10
Preetham R U

この 記事 は、強い、柔らかい、弱い、幻の参照を理解するのに非常に役立ちます。


概要を提供するには、

オブジェクトへの強い参照がある場合、オブジェクトはGC(ガベージコレクター)によって収集/再利用できません。

オブジェクトに対する弱い参照のみ(強い参照なし)しかない場合、そのオブジェクトは次のGCサイクルでGCによって回収されます。

オブジェクトへのソフト参照のみ(強力な参照なし)がある場合、JVMがメモリ不足になったときにのみオブジェクトはGCによって回収されます。

オブジェクトへのファントム参照を作成して、オブジェクトがReferenceQueueにエンキューされるタイミングを追跡します。細粒度のファイナライズを実行できることがわかったら。 (これにより、ファントム参照では参照先が提供されないため、誤ってオブジェクトを復活させることがなくなります)。詳細については、 this の記事を読むことをお勧めします。


つまり、強い参照にはltimate power(GCによって収集されることはありません)があると言えます。

ソフト参照は、弱い参照よりもpowerfulです(JVMがメモリを使い果たすまでGCサイクルをエスケープできるため)

弱い参照は、ソフト参照よりもさらに強力ではないです(GCサイクルを超えることができず、オブジェクトに他の強い参照がない場合は回収されます)。


レストランの類推

  • ウェイター-GC
  • あなた-ヒープ内のオブジェクト
  • レストランエリア/スペース-ヒープスペース
  • 新規顧客-レストランのテーブルを必要とする新規オブジェクト

強い顧客(強い参照に似ている)の場合、新しい顧客がレストランに来たり、何が起こっても、テーブル(ヒープ上のメモリ領域)を離れることはありません。 。ウェイターは、レストランを出るようにあなたに伝える権利を持ちません。

あなたがソフトカスタマー(ソフトリファレンスに似ている)の場合、新しいカスタマーがレストランに来ても、他の空のテーブルが残っていない限り、ウェイターはテーブルから離れることを求めません。新しい顧客。 (言い換えると、ウェイターは、新しい顧客が介入し、この新しい顧客に他のテーブルが残っていない場合にのみ、テーブルを離れるように求めます)

あなたが弱い顧客(弱い参照に類似)である場合、ウェイターは彼の意志で(いつでも)レストランを出るように頼むことができます:P

5
Lavish Kothari

強参照

これらは、毎日コーディングする通常のオブジェクト参照です。

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での参照の種類(強、弱、弱、幻)

5
Naresh Joshi