Ethan Nicholasによる、 弱い参照の理解 から:
弱い参照
簡単に言うと、weak referenceは、オブジェクトをメモリ内に保持するのに十分なほど強くない参照です。弱い参照はあなたがあなたにとって到達可能性を決定するためにガベージコレクタの能力を利用することを可能にします、それであなたはあなた自身でそれをする必要はありません。このように弱い参照を作成します。
WeakReference weakWidget = new WeakReference(widget);
そしてコードの他の場所で
weakWidget.get()
を使って実際のWidget
オブジェクトを取得することができます。もちろん、弱い参照はガベージコレクションを防ぐのに十分なほど強力ではないので、(ウィジェットへの強い参照がない場合)weakWidget.get()
が突然null
を返し始めることがあります。...
ソフト参照
soft referenceは、弱い参照とまったく同じですが、参照先のオブジェクトを破棄したくないという点が異なります。到達可能性が低いオブジェクト(最も強い参照は
WeakReferences
)は、次のガベージコレクションサイクルで破棄されますが、到達性が弱いオブジェクトは、しばらくの間は固執します。
SoftReferences
は、WeakReferences
とは異なる振る舞いをするためにrequiredではありませんが、実際には、メモリが十分にある限り、やさしく到達可能なオブジェクトは通常保持されます。オブジェクトがどの程度到達可能であるかについてガベージコレクタに心配させることができるので、これはそれらをキャッシュのための優れた基盤にします(強く到達可能なオブジェクトはneverキャッシュから削除されます)そしてそれがどれほどひどくそれらが消費しているメモリを必要とするか。
そしてPeter Kessler氏はコメントに次のように付け加えた。
Sun JREは、SoftReferencesをWeakReferencesとは異なる方法で扱います。利用可能なメモリにプレッシャーがない場合は、SoftReferenceによって参照されるオブジェクトを保持しようとします。 1つの詳細: "-client" JREと "-server" JREのポリシーは異なります。-client JREはヒープを拡張するのではなくSoftReferencesをクリアしてフットプリントを小さくしようとします。 SoftReferencesをクリアするのではなく(可能ならば)ヒープを拡張する方がパフォーマンスが高い。ワンサイズが全てに収まるわけではありません。
弱い参照は熱心に集められます。あるオブジェクトが弱く到達可能である(弱い参照を通してのみ到達可能である)とGCが判断した場合、GCはそのオブジェクトへの弱い参照を直ちにクリアします。そのため、クラスに関するキャッシュされたリフレクション情報やオブジェクトのラッパーなど、プログラムが「関連情報」を保持しているオブジェクトへの参照を保持するのに適しています。関連付けられているオブジェクトをGC処理した後に保持する意味はありません。弱い参照がクリアされると、コードが参照している参照キューにエンキューされ、関連付けられているオブジェクトも破棄されます。つまり、オブジェクトに関する追加情報を保持しますが、そのオブジェクトが参照するオブジェクトがなくなった後は、その情報は必要ありません。実際には、特定の状況では、WeakReferenceをサブクラス化して、オブジェクトに関する関連追加情報をWeakReferenceサブクラスのフィールドに保持することもできます。 WeakReferenceのもう1つの典型的な用途は、正規インスタンスを保持するためのMapsとの組み合わせです。
一方、SoftReferencesは、GCが通常それらのクリアを遅らせるので、外部の再現可能なリソースをキャッシュするのに適しています。ただし、OutOfMemoryErrorがスローされる前にすべてのSoftReferencesがクリアされることが保証されているので、理論的にはOOME [*]を引き起こすことはできません。
典型的なユースケースの例は、ファイルから内容の解析された形式を保持することです。ファイルをロードし、それを解析し、解析された表現のルートオブジェクトへのSoftReferenceを保持するシステムを実装します。次回ファイルが必要になったときには、SoftReferenceを使用してファイルを取得しようとします。あなたがそれを検索することができれば、あなたはあなた自身に別のロード/パースを免れ、そしてその間にGCがそれをクリアしたなら、あなたはそれをリロードします。そうすれば、パフォーマンスの最適化のために空きメモリを利用できますが、OOMEを危険にさらすことはありません。
今[*]のために。 SoftReferenceを保持しても、それ自体でOOMEを引き起こすことはありません。一方、タスクに対してSoftReferenceを誤って使用することを意図している場合(つまり、Objectに関連付けられた情報を何らかの方法で強く参照し、Referenceオブジェクトがクリアされたときにそれを破棄する)、 ReferenceQueueをポーリングして関連付けられているオブジェクトを破棄するコードは、タイムリーに実行されないことがあります。
そのため、構築にはコストがかかりますが、それでも他のデータから再構築可能な情報をキャッシュする場合は、決定は使用法によって異なります。あるデータの正規インスタンスへの参照を保持する場合は、オブジェクトを「所有」せずにオブジェクトへの参照を持つ(つまり、GCされないようにする)には、弱い参照を使用します。
Javaの場合;最強から最弱への順序で、強い、柔らかい、弱い、ファントムがあります。
A厳密参照は、参照オブジェクトをGCによる収集から保護する通常の参照です。すなわち、ゴミ収集することはありません。
Aソフト参照はガベージコレクタによる収集に適していますが、おそらくそのメモリが必要になるまで収集されません。すなわち、ゴミはOutOfMemoryError
の前に集まります。
弱い参照は、参照オブジェクトをGCによる収集から保護しない参照です。すなわち、強いまたは弱い参照がないときにゴミが溜まる。
ファントム参照は、オブジェクトへの参照がファイナライズされた後、割り当てられたメモリが再生される前にファントム参照されます。
アナロジー:JVMは王国、Objectは王国の王、GCは王(オブジェクト)を殺そうとする王国の攻撃者と仮定します。
弱い参照http://docs.Oracle.com/javase/1.5.0/docs/api/Java/lang/ref/WeakReference .html
原則:weak reference
はガベージコレクションに関連しています。通常、1つ以上のreference
を持つオブジェクトはガベージコレクションの対象にはなりません。
上記の原則は、weak reference
の場合は適用されません。あるオブジェクトが他のオブジェクトとの弱い参照しかない場合は、ガベージコレクションの準備ができています。
以下の例を見てみましょう。Objectsを含むMap
があります。ここで、Keyはオブジェクトを参照しています。
import Java.util.HashMap;
public class Test {
public static void main(String args[]) {
HashMap<Employee, EmployeeVal> aMap = new
HashMap<Employee, EmployeeVal>();
Employee emp = new Employee("Vinoth");
EmployeeVal val = new EmployeeVal("Programmer");
aMap.put(emp, val);
emp = null;
System.gc();
System.out.println("Size of Map" + aMap.size());
}
}
さて、プログラムの実行中にemp = null
を作成しました。キーを保持しているMap
はnull
であるため、ここでは意味がありません。上記の状況では、オブジェクトはガベージコレクションされません。
WeakHashMap
WeakHashMap
は、エントリ(key-to-value mappings
)がMap
から取得できなくなったときに削除される場所です。
上記の例をWeakHashMapと同じように見せてください。
import Java.util.WeakHashMap;
public class Test {
public static void main(String args[]) {
WeakHashMap<Employee, EmployeeVal> aMap =
new WeakHashMap<Employee, EmployeeVal>();
Employee emp = new Employee("Vinoth");
EmployeeVal val = new EmployeeVal("Programmer");
aMap.put(emp, val);
emp = null;
System.gc();
int count = 0;
while (0 != aMap.size()) {
++count;
System.gc();
}
System.out.println("Took " + count
+ " calls to System.gc() to result in weakHashMap size of : "
+ aMap.size());
}
}
出力:20 calls to System.gc()
を使用して、aMap size
of:0にしました。
WeakHashMap
はキーへの弱い参照のみを持ち、他のMap
クラスのような強い参照は持ちません。 WeakHashMap
を使用しているにもかかわらず、値またはキーが強く参照されている場合には注意が必要な状況があります。これをオブジェクトをWeakReferenceでラップすることで回避できます。
import Java.lang.ref.WeakReference;
import Java.util.HashMap;
public class Test {
public static void main(String args[]) {
HashMap<Employee, EmployeeVal> map =
new HashMap<Employee, EmployeeVal>();
WeakReference<HashMap<Employee, EmployeeVal>> aMap =
new WeakReference<HashMap<Employee, EmployeeVal>>(
map);
map = null;
while (null != aMap.get()) {
aMap.get().put(new Employee("Vinoth"),
new EmployeeVal("Programmer"));
System.out.println("Size of aMap " + aMap.get().size());
System.gc();
}
System.out.println("Its garbage collected");
}
}
ソフト参照。
Soft Reference
は、その弱い参照よりもわずかに強力です。ソフト参照はガベージコレクションを可能にしますが、他のオプションがない場合にのみガベージコレクタにクリアするように要求します。
ガベージコレクタは、到達性の弱いオブジェクトとは異なり、到達性の低いオブジェクトを積極的には収集しません。代わりに、実際にメモリを「必要とする」場合にのみ到達可能なオブジェクトを収集します。ソフトリファレンスはガベージコレクタに「メモリが足りない限りこのオブジェクトを残しておきたいのですが、メモリが非常にタイトになった場合は先に進んで収集して対処してください。それと。"ガベージコレクタは、OutOfMemoryError
をスローする前に、すべてのソフト参照をクリアする必要があります。
ソフトリファレンスとウィークリファレンスの唯一の違いは、
ガベージコレクタはアルゴリズムを使用して、到達しにくいオブジェクトを再生するかどうかを決定しますが、到達しにくいオブジェクトを常に再生します。
SoftReference
はキャッシュ用に設計されています。 WeakReference
が他の方法ではアクセスできないオブジェクトを参照していることが判明すると、それは直ちにクリアされます。 SoftReference
はそのままにしておくことができます。通常、空きメモリの量と、それをクリアする必要があるかどうかを判断するために最後に使用された時間に関するアルゴリズムがいくつかあります。現在のSunのアルゴリズムでは、Javaヒープ上の空きメモリのメガバイト数を超えて使用されていない場合、参照を消去します(設定可能、サーバーHotSpotは-Xmx
で設定された最大可能ヒープに対してチェックします)。別の方法で到達可能でない限り、SoftReference
はOutOfMemoryError
がスローされる前にクリアされます。
この 記事 は、強力な参照、弱い参照、弱い参照、およびファントム参照を理解するのに非常に役立ちます。
概要を説明します。
オブジェクトへの弱い参照しかない(強い参照がない)場合、そのオブジェクトは次のGCサイクルでGCによって回収されます。
オブジェクトへのソフト参照のみ(強力な参照なし)がある場合は、JVMによってメモリが不足した場合にのみ、オブジェクトはGCによって再利用されます。
だから、あなたはそれを言うことができる、強い参照は究極の力を持っている(GCによって収集することはできません)
弱い参照は弱い参照よりも強力な(JVMがメモリ不足になるまでGCサイクルを回避できるため)
弱い参照はソフト参照よりも強力ではありません(GCサイクルを超えることはできず、オブジェクトに他の強い参照がない場合は再利用されるため)。
レストランアナロジー
今、あなたが強い顧客(強い参照に類似している)であるならば、たとえ新しい顧客がレストランに来たとしても、あるいはこれまでに何が起こっても、あなたは決してあなたのテーブル(メモリ領域)を離れないヒープ上)。ウェイターには、レストランを出るように言う(またはあなたに要求する)権利はありません。
あなたがソフトカスタマーである場合(ソフトリファレンスに似ています)、新しいカスタマーがレストランに来た場合、ウェイターは他に空のテーブルがない限りテーブルを離れるように求めません。新しい顧客を収容するために残しました。 (言い換えれば、ウェイターは、新しい顧客が入ってきて、この新しい顧客のために他のテーブルが残っていない場合にのみテーブルを離れるように頼みます)
あなたが弱い顧客(弱い参照に似ている)なら、ウェイターは彼の意志で、(いつでも)レストランを去るように頼むことができる:P
Javaにおける6種類のオブジェクト到達可能性状態 -
詳細については: https://www.artima.com/insidejvm/ed2/gc16.html "折りたたむ
弱参照オブジェクトは、弱参照しかない場合にのみ収集されることに注意してください。 1つの強力な参照がある場合、それがいくつの弱い参照を持っていても収集されません。
動作中のメモリ使用量の側面を示すために、プログラムの最後まで保持することにより、重いオブジェクトで重い負荷がかかった状態で、Strong、Soft、Weak、Phantom参照の実験を行いました。次に、監視されたヒープ使用量とGC動作。これらのメトリックはケースごとに異なる場合がありますが、確実に高レベルの理解を提供します。以下は調査結果です。
高負荷時のヒープとGCの動作
より詳細な情報を取得できます グラフ、統計、この実験の観察はこちら 。
WeakReference:弱い参照しかないオブジェクトは、すべてのGCサイクル(マイナーまたはフル)で収集されます。
SoftReference:ソフト参照のみが行われるオブジェクトが収集されるタイミングは、次の要素によって異なります。
-XX:SoftRefLRUPolicyMSPerMB = Nフラグ(デフォルト値は1000、別名1秒)
ヒープ内の空きメモリの量.
例:
最後にアクセスされた時刻が10秒より大きい場合、SoftReferenceによってのみ参照されるオブジェクトが収集されます。