Javaの4種類の参照タイプ

4953 ワード

JDK 1.2以前のバージョンでは、オブジェクトが変数によって参照されない場合、プログラムはこのオブジェクトを使用できません.つまり、オブジェクトがタッチ可能(reachable)状態にある場合にのみ、プログラムが使用できます.JDK 1.2以降、オブジェクトの参照を4つのレベルに分けて、プログラムがオブジェクトのライフサイクルをより柔軟に制御できるようにします.この4つのレベルは、強参照、ソフト引用、弱参照、虚参照の順に高くなります.1、強参照(StrongReference)強参照は最も一般的な参照です.オブジェクトに強い参照がある場合、ゴミ回収器は決してそれを回収しません.メモリ容量が不足している場合、Java仮想マシンはOutOfMemoryErrorエラーを投げ出してプログラムを異常に終了させ、強参照のあるオブジェクトを勝手に回収してメモリ不足の問題を解決することはありません.ps:強参照は実は私たちは普段A a=new A()という意味です.2、ソフトリファレンス(SoftReference)1つのオブジェクトにソフトリファレンスしかない場合、メモリ容量が十分であればゴミ回収器は回収しません.メモリ容量が不足している場合、これらのオブジェクトのメモリは回収されます.ゴミ回収器が回収していない限り、そのオブジェクトはプログラムで使用できます.ソフトリファレンスはメモリに敏感なキャッシュを実現するために使用できます(以下、例を示します).ソフトリファレンスは、リファレンスキュー(ReferenceQueue)と組み合わせて使用できます.ソフトリファレンスが参照したオブジェクトがゴミ回収器で回収されると、Java仮想マシンはこのソフトリファレンスを関連付けられたリファレンスキューに追加します.3、弱リファレンス(WeakReference)弱い参照とソフト参照の違いは、弱い参照のみを持つオブジェクトがより短いライフサイクルを持つことです.ゴミ回収スレッドが管轄するメモリ領域をスキャンする過程で、弱い参照のみを持つオブジェクトが見つかった場合、現在のメモリ領域が十分かどうかにかかわらず、メモリが回収されます.ただし、ゴミ回収器は優先的ですレベルの低いスレッドなので、弱い参照のみを持つオブジェクトをすぐに見つけるとは限りません.弱いリファレンスはリファレンスキュー(ReferenceQueue)と組み合わせて使用できます.弱いリファレンスが参照するオブジェクトがゴミ回収されると、Java仮想マシンはこの弱いリファレンスを関連付けられたリファレンスキューに追加します.4、ダミーリファレンス(PhantomReference)「ダミーリファレンス」名前の通り、形は虚構であり、他のいくつかの参照とは異なり、虚参照はオブジェクトのライフサイクルを決定しません.オブジェクトがダミー参照のみを持っている場合は、参照がない場合と同様に、いつでもゴミ回収機によって回収される可能性があります.ダミーリファレンスは、主にオブジェクトがゴミ回収器で回収されたアクティビティを追跡するために使用されます.ダミーリファレンスとソフトリファレンスと弱リファレンスの違いは、ダミーリファレンスがリファレンスキュー(ReferenceQueue)と組み合わせて使用される必要があることです.ゴミ回収器がオブジェクトを回収する準備をしているときに、ダミーリファレンスがあることに気づいたら、オブジェクトのメモリを回収する前に、このダミーリファレンスを関連付けられたリファレンスキューに追加します.
ReferenceQueue queue = new ReferenceQueue();
PhantomReference pr = new PhantomReference(object, queue); 
プログラムは、参照キューに虚参照が含まれているかどうかを判断することによって、参照されたオブジェクトがゴミ回収されるかどうかを知ることができる.プログラムが虚参照が参照キューに追加されていることを発見した場合、参照されたオブジェクトのメモリが回収される前に必要な行動をとることができます.
ソフトリファレンスを使用して機密データのキャッシュを構築する1、なぜソフトリファレンスを使用する必要があるのか
まず、従業員情報照会システムの例を見てみましょう.Java言語で実装された従業員情報クエリーシステムを使用して、ディスクファイルまたはデータベースに格納されている従業員人事ファイル情報をクエリーします.ユーザーとして、数分か数秒前に確認した従業員プロファイル情報を振り返る必要がある可能性があります(同様に、WEBページを閲覧するときも「戻る」ボタンを使用することがよくあります).この場合、過去に見た従業員情報をメモリに保存する2つのプログラムの実装方法があります.1つは、従業員ファイル情報を格納したJavaオブジェクトのライフサイクルがアプリケーション全体を貫くことです.もう1つは、ユーザが他の従業員のファイル情報の表示を開始すると、現在表示されている従業員のファイル情報を格納したJavaオブジェクトの参照を終了し、ゴミ収集スレッドが占有するメモリ領域を回収し、ユーザが再び従業員のファイル情報を閲覧する必要がある場合に、従業員の情報を再構築することである.明らかに、第1の実装方法は大量のメモリ浪費をもたらすが、第2の実装の欠点は、ゴミ収集スレッドがゴミ収集を行っていない場合でも、従業員のファイル情報を含むオブジェクトがメモリに完全に保存されている場合でも、アプリケーションがオブジェクトを再構築することである.ディスク・ファイルへのアクセス、ネットワーク・リソースへのアクセス、データベースのクエリーなどの操作は、アプリケーションの実行性能に影響を与える重要な要素であり、まだ回収されていないJavaオブジェクトの参照を再取得できれば、不要なアクセスを削減し、プログラムの実行速度を大幅に向上させることがわかります.
2、ソフトリファレンスを使用する場合
SoftReferenceの特徴は、Javaオブジェクトへのソフトリファレンスを保存するインスタンスです.このソフトリファレンスの存在は、ゴミ収集スレッドによるJavaオブジェクトの回収を妨げません.すなわち,SoftReferenceが1つのJavaオブジェクトへのソフトリファレンスを保存すると,スパムスレッドがこのJavaオブジェクトを回収する前に,SoftReferenceクラスが提供するget()メソッドはJavaオブジェクトの強いリファレンスを返す.また、スパムスレッドがJavaオブジェクトを回収すると、get()メソッドはnullを返します.
次のコードを見てください.
MyObject aReference= new MyObject();
SoftReference aSoftRef=new SoftReference(aReference); 
このとき、このMyObjectオブジェクトには、ソフトリファレンスからソフトリファレンス、変数aReferenceからの強いリファレンスの2つのリファレンスパスがあるので、このMyObjectオブジェクトは強力なオブジェクトです.
次に、このMyObjectインスタンスに対するaReferenceの強い参照を終了します.
aRef = null;
以降、このMyObjectオブジェクトはソフト可及オブジェクトとなった.ゴミ収集スレッドがメモリゴミ収集を行う場合、オブジェクトに対するSoftReferenceの参照があるからといって、オブジェクトは常に保持されません.Java仮想マシンのゴミ収集スレッドは、ソフトおよびオブジェクトと他の一般的なJavaオブジェクトを区別します.ソフトおよびオブジェクトのクリーンアップは、ゴミ収集スレッドが特定のアルゴリズムに基づいてメモリのニーズに応じて決定します.つまり、ゴミ収集スレッドは、仮想マシンがOutOfMemoryErrorを放出する前にソフト可及オブジェクトを回収し、仮想機会は長時間放置されているソフト可及オブジェクトをできるだけ優先的に回収し、構築されたばかりまたは使用されたばかりの「新しい」ソフト可反オブジェクトは仮想マシンにできるだけ保持されます.これらのオブジェクトを回収する前に、次のことができます.
MyObject anotherRef=(MyObject)aSoftRef.get(); 
は、このインスタンスに対する強い参照を再取得する.回収後、get()メソッドを呼び出すとnullしか得られません.
3、ReferenceQueueでソフトリファレンスを失ったSoftReferenceをクリアする
Javaオブジェクトとして、SoftReferenceオブジェクトはソフトリファレンスを保存する特殊性に加えて、Javaオブジェクトの一般性もあります.したがって、ソフト・アクセシビリティ・オブジェクトが回収された後、このSoftReferenceオブジェクトのget()メソッドはnullを返すが、このSoftReferenceオブジェクトはもはや存在する価値がなく、大量のSoftReferenceオブジェクトによるメモリ漏洩を回避する適切な消去メカニズムが必要である.javaでlang.refパッケージにはReferenceQueueも提供されています.SoftReferenceオブジェクトを作成するときに、次のようなパラメータとしてReferenceQueueオブジェクトを使用します.
ReferenceQueue queue = new ReferenceQueue();
SoftReference ref=new SoftReference(aMyObject, queue); 
では、このSoftReferenceによってソフトリファレンスされたaMyOhjectがゴミ収集器によって回収されると同時に、refによって強くリファレンスされたSoftReferenceオブジェクトがReferenceQueueに登録される.つまり、ReferenceQueueに保存されているオブジェクトはReferenceオブジェクトであり、ソフトリファレンスされたオブジェクトを失ったReferenceオブジェクトである.また、ReferenceQueueという名前からも分かるように、poll()メソッドを呼び出すと、このキューに空のキューがなければ、キューの前のReferenceオブジェクトに戻ります.
いつでも、ReferenceQueueのpoll()メソッドを呼び出して、関心のある非強力なオブジェクトが回収されているかどうかを確認することができます.キューが空の場合、nullが返されます.そうでない場合、メソッドはキューの前のReferenceオブジェクトを返します.この方法を利用して,どのSoftReferenceがソフトリファレンスしたオブジェクトが回収されたかを調べることができる.ソフトリファレンスを失ったオブジェクトのSoftReferenceオブジェクトを消去できます.一般的な方法は次のとおりです.
SoftReference ref = null;
while ((ref = (EmployeeRef) q.poll()) != null) {
	//   ref
}