Java:強い/柔らかい/弱い/幻の参照の違い


178

私はこのトピックについてこの記事を読みましたが、私はそれを本当に理解していません。コンセプトを説明する際に、例とともにアドバイスをお願いします。



4
私はそのドキュメントを読んだのですが、どのような違いがあるか想像するのに役立ちません。(たぶん、それがハードに読まれたドキュメントであるからです)

14
その記事を読んでも理解できない場合、それについて特定の質問がありますか?「Fooを私に説明してください」、「意味はここにあります」、「わかりません」には、取得できない部分の詳細がなければ対応するのは困難です。
yshavit 2012年


@LouisWassermanトップリンクは無効になりました。
Mehraj Malik

回答:


142

Javaは、二つの異なるタイプ/クラス提供して参照オブジェクト強い弱いです。弱参照オブジェクトは、さらにソフトファントムに分類できます。

  • 強い
  • 弱い
    • 柔らかい
    • ファントム

ポイントごとに行きましょう。

強い参照オブジェクト

StringBuilder builder = new StringBuilder();

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

弱い参照オブジェクト

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

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

弱さのレベル

ソフトファントムの 2つの異なるレベルの弱点を登録できます。

ソフト参照オブジェクトがそのメモリ内に残り、もう少し基本的に弱参照オブジェクトである:利用可能なメモリがないとのリスクがあるまで、通常は、GCサイクルに耐えるOutOfMemoryError(その場合、それを除去することができるが)。

一方、ファントム参照オブジェクトがオブジェクトのみが効果的にメモリから削除されましたを正確に知っておくと便利です:通常、それらが固定するために使用されている奇妙なファイナライズ()復活/復活の行動を、彼らは実際にはオブジェクト自身を返しませんので、しかし、彼らの記憶の存在を追跡するのを助けるだけです。

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


76

弱い参照:

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

ソフトリファレンス:

ソフト参照は弱参照とまったく同じですが、参照先のオブジェクトを捨てたくないという点が異なります。到達可能性が低いオブジェクト(オブジェクトへの最も強い参照はWeakReferencesです)は、次のガベージコレクションサイクルで破棄されますが、到達可能性が低いオブジェクトは、通常しばらくの間留まります。

ファントム参照:

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

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


1
この回答のすべてが正しいように見えますが、リンクされたWebページにエラーがある可能性があるようにも見えます。パッケージjava.lang.refとPhantomReference のJavadocは、オブジェクトが「ファントム到達可能」でなくなるまでガベージコレクションされないことを示唆しています。つまり、(SoftReferenceとは異なり)PhantomReferenceは、参照するオブジェクトの前にデキューする必要があります。ガベージコレクションされます...そしてキューに入れられても、関連するメモリが解放されたことを示しません。
セオドアマードック

2
念のため、私はむしろ、そのブログ投稿が正しい世界に住みたいと思っています。
セオドアマードック

1
@TheodoreMurdock javadocは正しいです。ファントム参照は、ガベージコレクションをまったく妨げません。オブジェクトがエンキューされると、ファイナライザーはすでに実行されているため、ファイナライザーによっても保存できません。死んでいるが、まだなくなっていない。
Leliel 2016年

@Leliel実際には、ファントム参照実際にキューに入れられた後のガベージコレクションを妨げます...私は最近、バグが原因でクリーンアップスレッドが早く終了したときにこれを実現しました。ファントム参照の存在は、すべてのファントム参照オブジェクトがヒープダンプに保持され、収集に利用できないことを保証するのに十分でした...キューの処理に失敗した場合、またはキューの処理時にファントム参照をgcに適格にできなかった場合(ファントム参照をclear()しないでください)、メモリリークにはファントム参照と参照先オブジェクトの両方が含まれます。
Theodore Murdock

25

との単純な違いはSoftReferenceAndroid DeveloperWeakReferenceによって提供されます

a SoftReferenceとa の違いはWeakReference、参照をクリアしてエンキューすることを決定する時点です。

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

  • WeakReference弱参照であることが判明するとすぐに、A をクリアしてキューに入れることができます。


16

使用した3つの用語は、主にガベージコレクションを取得するObjectの資格に関連しています。

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

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

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

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

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

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


3
これは間違っていると思います。「ガベージコレクターが最初のライフサイクル自体で弱い参照を収集すると、ガベージコレクションの次のサイクルで弱い参照が収集されます。」必ずしもそうではありませんが、GCの連続実行でそれらが確実に発生するようにするにはどうすればよいですか?GCは、ソフト参照オブジェクトを2回目と3回目でも実行できるようにすることができます。そのためのドキュメントはありません。その場合は、リンクを明記してください。
Saurabh Patil、2014年

2
また、あなたの答えは少し曖昧です。この文を見てください。「弱参照と同じくらい多かれ少なかれ同じです。しかし、ガベージコレクションからの弱い参照よりもオブジェクトを少し強く保持していると言えます。-彼は明らかに類似点ではなく相違点について尋ねています。これらの単語はすべて、トピックを明確にするよりも混乱を招きます。
Saurabh Patil、2014年

@SaurabhPatil-コメントがありませんでした。答えはここに行く。1.「彼は明確に相違点について尋ねており、類似点ではない」-質問の説明を参照してください(タイトルだけではなく)「アドバイスを教えてください。説明する例をいくつか教えてください」。2.「しかし、それはオブジェクトをもう少し保持していると言えます...」SOFには、反対票を投じて新しい答えを与えるオプションもあると思います。
Sabya 2015

14

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


要約すると、

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

弱い参照しかない場合オブジェクトへのある場合(強い参照がない場合)、オブジェクトは次のGCサイクルでGCによって再利用されます。

オブジェクトへのソフト参照のみ(強い参照なし)がある場合、オブジェクトは、JVMがメモリを使い果たしたときにのみ、GCによって再利用されます。

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


つまり、強い参照には究極の力がありますがあります(GCで収集することはできません)。

ソフト参照は弱い参照よりも強力です(JVMがメモリ不足になるまでGCサイクルを回避できるため)。

弱い参照は、ソフト参照よりも強力ではありません(オブジェクトが他の強い参照を持たない場合は、GCサイクルをエスケープできず、再利用されるため)。


レストランのアナロジー

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

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

あなたがいる場合には、ソフトの顧客(ソフト参照に類似した)新しい顧客はレストランに来た場合、その後、ウェイターが新しい顧客を収容するために残された他の空のテーブルが存在しない場合を除き、テーブルを残すように頼むことはありません。(言い換えれば、ウェイターは、新しい顧客が参加し、この新しい顧客のために残っている他のテーブルがない場合にのみ、テーブルを離れるように求めます)

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


10

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

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

弱い-GCの対象となるリファレンスです。

Soft-メモリが使用可能になるまでオブジェクトがGCに適格な一種の参照です。画像キャッシュに最適です。メモリが使用可能になるまで保持されます。

ファントム-GCに直接適格なオブジェクトを持つ一種の参照です。オブジェクトがメモリから削除されたときを知るためにのみ使用されます。

使用:

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

  2. ときfinalize()メソッドがオーバーロードされ、その後、GCは、2つのクラスのGC対象とするオブジェクトのためにタイムリーに行われない場合があります。したがって、ファントム参照により、それらはGC beforeの対象になります。これが、ヒープの大部分がガベージである場合でもOutOfMemoryErrorsfinalize()を取得できる理由です。

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


10

強い参照

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

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での参照のタイプ(ストロング、ソフト、ウィーク、ファントム)」を参照してください。


あなたは、弱い屈折が他の屈折から屈折されない場合、次のサイクルでGCされると書いています...しかし、屈折をストロンするために同じことが起こるべきではありませんか?stron refrenceにアクセスしない場合はクリアされます...許可されている場合、違いはどこにありますか?#confused
filemonczyk

1
オブジェクトがs1(強い)やs2(強い)などから参照されている場合、オブジェクトはs1とs2の両方が逆参照されるまでガベージコレクションの対象にはなりませんが、オブジェクトがs1(弱い)とs2( strong)s1は弱い参照であり、オブジェクトが弱い参照以外に他の参照を持たない場合、オブジェクトはs2のみから逆参照されると、次のGCサイクルでガベージコレクションの対象になります
Naresh Joshi
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.