web-dev-qa-db-ja.com

JavaのSoftReferenceとWeakReferenceの違いは何ですか?

759
driekken

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をクリアするのではなく(可能ならば)ヒープを拡張する方がパフォーマンスが高い。ワンサイズが全てに収まるわけではありません。

873
Michael Myers

弱い参照は熱心に集められます。あるオブジェクトが弱く到達可能である(弱い参照を通してのみ到達可能である)とGCが判断した場合、GCはそのオブジェクトへの弱い参照を直ちにクリアします。そのため、クラスに関するキャッシュされたリフレクション情報やオブジェクトのラッパーなど、プログラムが「関連情報」を保持しているオブジェクトへの参照を保持するのに適しています。関連付けられているオブジェクトをGC処理した後に保持する意味はありません。弱い参照がクリアされると、コードが参照している参照キューにエンキューされ、関連付けられているオブジェクトも破棄されます。つまり、オブジェクトに関する追加情報を保持しますが、そのオブジェクトが参照するオブジェクトがなくなった後は、その情報は必要ありません。実際には、特定の状況では、WeakReferenceをサブクラス化して、オブジェクトに関する関連追加情報をWeakReferenceサブクラスのフィールドに保持することもできます。 WeakReferenceのもう1つの典型的な用途は、正規インスタンスを保持するためのMapsとの組み合わせです。

一方、SoftReferencesは、GCが通常それらのクリアを遅らせるので、外部の再現可能なリソースをキャッシュするのに適しています。ただし、OutOfMemoryErrorがスローされる前にすべてのSoftReferencesがクリアされることが保証されているので、理論的にはOOME [*]を引き起こすことはできません。

典型的なユースケースの例は、ファイルから内容の解析された形式を保持することです。ファイルをロードし、それを解析し、解析された表現のルートオブジェクトへのSoftReferenceを保持するシステムを実装します。次回ファイルが必要になったときには、SoftReferenceを使用してファイルを取得しようとします。あなたがそれを検索することができれば、あなたはあなた自身に別のロード/パースを免れ、そしてその間にGCがそれをクリアしたなら、あなたはそれをリロードします。そうすれば、パフォーマンスの最適化のために空きメモリを利用できますが、OOMEを危険にさらすことはありません。

今[*]のために。 SoftReferenceを保持しても、それ自体でOOMEを引き起こすことはありません。一方、タスクに対してSoftReferenceを誤って使用することを意図している場合(つまり、Objectに関連付けられた情報を何らかの方法で強く参照し、Referenceオブジェクトがクリアされたときにそれを破棄する)、 ReferenceQueueをポーリングして関連付けられているオブジェクトを破棄するコードは、タイムリーに実行されないことがあります。

そのため、構築にはコストがかかりますが、それでも他のデータから再構築可能な情報をキャッシュする場合は、決定は使用法によって異なります。あるデータの正規インスタンスへの参照を保持する場合は、オブジェクトを「所有」せずにオブジェクトへの参照を持つ(つまり、GCされないようにする)には、弱い参照を使用します。

196
driekken

Javaの場合;最強から最弱への順序で、強い、柔らかい、弱い、ファントムがあります。

A厳密参照は、参照オブジェクトをGCによる収集から保護する通常の参照です。すなわち、ゴミ収集することはありません。

Aソフト参照はガベージコレクタによる収集に適していますが、おそらくそのメモリが必要になるまで収集されません。すなわち、ゴミはOutOfMemoryErrorの前に集まります。

弱い参照は、参照オブジェクトをGCによる収集から保護しない参照です。すなわち、強いまたは弱い参照がないときにゴミが溜まる。

ファントム参照は、オブジェクトへの参照がファイナライズされた後、割り当てられたメモリが再生される前にファントム参照されます。

出典

アナロジー:JVMは王国、Objectは王国の王、GCは王(オブジェクト)を殺そうとする王国の攻撃者と仮定します。

  • キングが強いのとき、GCは彼を殺すことはできません。
  • KingがSoftのとき、GCは彼を攻撃しますが、王はリソースが利用可能になるまで保護をもって王国を統治します。
  • キングが弱いとき、GCは彼を攻撃しますが保護なしで王国を支配します。
  • 王がファントムのとき、GCはすでに彼を殺したが王は彼の魂を介して利用可能です。
124
Premraj

弱い参照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を作成しました。キーを保持しているMapnullであるため、ここでは意味がありません。上記の状況では、オブジェクトはガベージコレクションされません。

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をスローする前に、すべてのソフト参照をクリアする必要があります。

70
Thalaivar

ソフトリファレンスとウィークリファレンスの唯一の違いは、

ガベージコレクタはアルゴリズムを使用して、到達しにくいオブジェクトを再生するかどうかを決定しますが、到達しにくいオブジェクトを常に再生します。

46

SoftReferenceはキャッシュ用に設計されています。 WeakReferenceが他の方法ではアクセスできないオブジェクトを参照していることが判明すると、それは直ちにクリアされます。 SoftReferenceはそのままにしておくことができます。通常、空きメモリの量と、それをクリアする必要があるかどうかを判断するために最後に使用された時間に関するアルゴリズムがいくつかあります。現在のSunのアルゴリズムでは、Javaヒープ上の空きメモリのメガバイト数を超えて使用されていない場合、参照を消去します(設定可能、サーバーHotSpotは-Xmxで設定された最大可能ヒープに対してチェックします)。別の方法で到達可能でない限り、SoftReferenceOutOfMemoryErrorがスローされる前にクリアされます。

22

この 記事 は、強力な参照、弱い参照、弱い参照、およびファントム参照を理解するのに非常に役立ちます。


概要を説明します。

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

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


だから、あなたはそれを言うことができる、強い参照は究極の力を持っている(GCによって収集することはできません)

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

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


レストランアナロジー

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

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

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

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

7
Lavish Kothari

Javaにおける6種類のオブジェクト到達可能性状態 -

  1. 強い到達可能なオブジェクト - GC できません収集(占有されているメモリを回収する)_この種のオブジェクト。これらはルートノードまたは別の強く到達可能なオブジェクトを介して到達可能(すなわちローカル変数、クラス変数、インスタンス変数などを介して)です。
  2. ソフト到達可能なオブジェクト - GC 試みる可能性がありますメモリの競合に応じてこの種のオブジェクトを収集します。これらは1つ以上のsoft reference objectsを介してルートから到達可能です。
  3. 到達可能なオブジェクト - GC 必須この種のオブジェクトを収集します。これらは1つ以上の弱参照オブジェクトを介してルートから到達可能です。
  4. Resurrect-able個のオブジェクト - GCは既にこれらのオブジェクトを収集中です。しかし、いくつかのファイナライザを実行することでこれらはいずれかの状態に戻る可能性があります - 強い/柔らかい/弱い
  5. Phantomly到達可能なオブジェクト - GC 既にこれらのオブジェクトを収集している最中で、どのファイナライザによっても復活できないと判断された場合(finalize()メソッドを宣言している場合)実行されています)。これらは1つ以上のファントム参照オブジェクトを介してルートから到達可能です。
  6. nreachable object - オブジェクトは、強くも、弱くも、弱くも、ファントムにも到達できず、また復活できません。これらのオブジェクトはレクラメーションの準備ができています

詳細については: https://www.artima.com/insidejvm/ed2/gc16.html "折りたたむ

3
V.Vidyasagar

弱参照オブジェクトは、弱参照しかない場合にのみ収集されることに注意してください。 1つの強力な参照がある場合、それがいくつの弱い参照を持っていても収集されません。

1
Fai Lau

動作中のメモリ使用量の側面を示すために、プログラムの最後まで保持することにより、重いオブジェクトで重い負荷がかかった状態で、Strong、Soft、Weak、Phantom参照の実験を行いました。次に、監視されたヒープ使用量とGC動作。これらのメトリックはケースごとに異なる場合がありますが、確実に高レベルの理解を提供します。以下は調査結果です。

高負荷時のヒープとGCの動作

  • 強参照/ハード参照-プログラムの継続中、JVMは保持された強い参照オブジェクトを収集できませんでした。最終的に「Java.lang.OutOfMemoryError:Java heap space」になりました
  • ソフトリファレンス-プログラムの継続に伴い、ヒープ使用量は増加し続けましたが、最大ヒープに近づいているため、OLD gen GCが発生しました。 GCは、プログラムを開始してから少し遅れて開始しました。
  • 弱い参照-プログラムが開始されると、オブジェクトはすぐにファイナライズおよび収集され始めました。ほとんどのオブジェクトは、若い世代のガベージコレクションで収集されました。
  • ファントムリファレンス-弱いリファレンスと同様に、ファントムリファレンスオブジェクトもファイナライズされ、ガベージコレクションがすぐに開始されました。古い世代のGCはなく、すべてのオブジェクトは若い世代のガベージコレクション自体で収集されていました。

より詳細な情報を取得できます グラフ、統計、この実験の観察はこちら

0
Ravi K

WeakReference:弱い参照しかないオブジェクトは、すべてのGCサイクル(マイナーまたはフル)で収集されます。

SoftReference:ソフト参照のみが行われるオブジェクトが収集されるタイミングは、次の要素によって異なります。

  1. -XX:SoftRefLRUPolicyMSPerMB = Nフラグ(デフォルト値は1000、別名1秒)

  2. ヒープ内の空きメモリの量.

    例:

    • ヒープには10MBの空き容量があります(フルGC後)。
    • -XX:SoftRefLRUPolicyMSPerMB = 1000

    最後にアクセスされた時刻が10秒より大きい場合、SoftReferenceによってのみ参照されるオブジェクトが収集されます。

0
Artem Petrov