JAvaの弱い参照、ソフト参照、虚参照


Java 2プラットフォームにはjava.lang.refパッケージが導入されています.クラスには、メモリに残さずにオブジェクトを参照できます.これらのクラスはまた、ゴミ収集器(garbage collector)との限られたインタラクションを提供する.
      1.まず「強いものから弱いものまで」(ゴミ回収器との関係のみ)いくつかの基本概念を明確にする.      strong referencesは、あなたが通常確立しているreferenceです.このreferenceは強力です.これはゴミ回収機で自動的に回収されません.例:      StringBuffer buffer = new StringBuffer();      ここでこのbufferは強引用であり、「強」と呼ばれるのは、Garbage Collectorとの関係をどのように処理するかによって決まります.それはどうしても回収されません.とても強いです.強い引用は時々問題があり、下のハッシュテーブルの例が良い説明です.さらにもう1つの問題は、バッファ、特に画像などの大きな構造にある.メモリに画像バッファを配置する領域を開き、その領域を指すポインタを望んでいます.このとき、強いリファレンスを使用すると、画像がメモリに残るように強制されます.不要だと思ったら、手動で削除する必要があります.そうしないと、メモリが漏れます.
      WeakReferenceはあってもなくてもいいものに似ています.ゴミ回収機スレッドが管轄するメモリ領域をスキャンする過程で、弱い参照のみを持つオブジェクトが発見されると、現在のメモリ領域が十分かどうかにかかわらず、メモリが回収されます.つまり、strongはゴミ回収器にオブジェクトをメモリに残すように要求していません.ただし、ゴミ回収器は優先度の低いスレッドであるため、弱い参照のみを持つオブジェクトをすぐに発見するとは限らない.よく言われるUnreachableと弱引用は同じ意味を指す.これはまだはっきり言えないかもしれませんが、例を挙げます.      Widgetというクラスがありますが、何らかの理由で継承によって機能を追加することはできません.このオブジェクトから情報を取り出したい場合はどうすればいいですか?各Widgetのserial Numberを監視する必要があると仮定しますが、このWidgetにはこの属性がなく、継承できません.このとき、HashMaps:serialNumber Map.put(widget,widgetSerialNumber)を使用することを考えました.       これで終わりじゃないですか~表面的にはokのように見えますが、まさにWidgetというStrong Referenceに問題が発生しています.WidgetのSerialNumberが不要であることを設定すると、このマッピングテーブルからこのマッピングペアを除去します.そうしないと、メモリの漏洩やエラー(有効なSerialNumberが除去されます)が発生します.この問題はよく耳にしますが、はい、ゴミ管理メカニズムのない言語ではよくある問題です.JAVAでは心配しないでください.WeakReferenceがあるからです.私たちは内蔵のWeakHashMapクラスを使用しています.このクラスはハッシュテーブルHashMapとほぼ同じですが、キーキーの場所でWeakReferenceを使用しています.WeakHashMapキーがゴミになったら、対応するエントリが自動的に削除されます.これで上記の問題を解決しました~
      SoftReferenceもあってもなくてもいいものに似ています.メモリ容量が十分であれば、ゴミ回収器は回収されず、メモリ容量が不足している場合は、これらのオブジェクトのメモリが回収されます.ゴミ回収器が回収していない限り、そのオブジェクトはプログラムで使用できます.ソフトリファレンスは、メモリに敏感なキャッシュを実現するために使用できます.
      弱いリファレンスとソフトリファレンスの違いは、WeakReferenceを持つオブジェクトがより短いライフサイクルを持つことです.あるいは、SoftReferenceはWeakReferenceよりも回収対象に敏感ではありません.WeakReferenceオブジェクトは次のゴミ回収でクリーンアップされ、SoftReferenceオブジェクトはしばらく保存されます.SoftReferencesでは、WeakReferenceと異なることを自発的に要求することはありませんが、実際にはSoftReferenceオブジェクトはメモリに余裕がある場合には削除されません.つまり、バッファを作成するのに良い選択です.StrongReferenceとWeakReferenceのメリットを兼ね備えており、メモリにとどまることができ、メモリ不足で処理することができます.これはすべて自動的です.
      PhantomReferenceは「虚引用」であり、その名の通り、形は虚構であり、他のいくつかの引用とは異なり、虚引用はオブジェクトのライフサイクルを決定しません.オブジェクトが虚参照のみを持っている場合は、参照がない場合と同様に、getメソッドがいつでもnullを返す可能性があります.ダミーリファレンスは、主にオブジェクトがゴミ回収されたアクティビティを追跡するために使用されます.弱いリファレンスとソフトリファレンスとは最大の違いであるリファレンスキュー(ReferenceQueue)と組み合わせて使用する必要があります.     
      WeakReferenceはゴミ回収活動の前に対象を入隊させ、理論的にはfinalize()法で再生させることもできるが、WeakReferenceは死んでしまった.PhantomReferencesオブジェクトは、オブジェクトがメモリから消去されたときにエンキューされます.すなわち、ゴミ回収器がオブジェクトを回収する準備をしているときに、ダミー参照があることが判明すると、オブジェクトのメモリを回収する前に、このダミー参照を関連する参照キューに追加します.プログラムは、参照キューに虚参照が含まれているかどうかを判断することによって、参照されたオブジェクトがゴミ回収されるかどうかを知ることができる.プログラムは、仮想リファレンスがリファレンスキューに追加されていることを発見した場合、リファレンスされたオブジェクトのメモリが回収される前に必要な行動をとることができます.finalize()メソッドの使用を制限し、より安全で効率的です.
     2.このかばんが私たちにどんな種類を提供してくれたか見てみましょう.WeakReferenceクラスWeakReference weakref=new WeakReference(ref);      このようにweakrefは、refがオブジェクトを指すweak referenceである.このweak referenceが指すオブジェクトを参照するにはgetメソッドを使用します.オブジェクトのweak referenceをHashtableまたはキャッシュに入れ、strong referenceが彼らを指していない場合、オブジェクトをゴミ収集器で回収することができます.実際、WeakHashMapはこのことを専門にしています.WeakReferenceがgetメソッドを使用してnullを返すと、そのオブジェクトがゴミになり、このweakrefオブジェクトも役に立たなくなります.これはいくつかの清掃作業が必要です.ReferenceQueueクラスはこれを行い、ReferenceQueueクラスにWeakReferenceの構造方法を渡すと、参照が指すオブジェクトがゴミになると、この参照のオブジェクトが自動的にこの参照キューに挿入されます.このキューを一定時間間隔で処理できます.
SoftReferenceクラス     スマートキャッシュ(java.lang.ref.SoftReference is a relatively new class,used to implement smart caches.)を実装するために使用できます.
     大きな配列を指すオブジェクト参照があるとします.
Object obj = new char[1000000];     そして可能であれば、この配列をずっと保存するつもりですが、メモリが極めて不足している場合は、この配列を解放するのが好きです.ソフトウェアreference:SoftReference ref=new SoftReference(obj)を使用できます.      Objはこのソフトreferenceの参照です.後で、if(ref.get()==null)/(referent has been cleared)else//(referent has not been cleared)else//(referent has not been cleared)を検出します.       このリファレンスがクリアされると、ゴミ回収器は使用するスペースを回収し、キャッシュされたオブジェクトも消えます.このインジケータに別の参照がある場合、ゴミ回収器はそれを除去しません.このスキームは、可能な限りオブジェクトが常に保存されるが、メモリの緊張したオブジェクトが消去されることを特徴とする様々なタイプのキャッシュを実現するために使用することができる.      注意:ソフトリファレンスはリファレンスキュー(ReferenceQueue)と組み合わせて使用できます.ソフトリファレンスが参照するオブジェクトがゴミ回収されると、Java仮想マシンはこのソフトリファレンスを関連するリファレンスキューに追加します.
 
ごみ収集時の表現を例に挙げてみましょう.
 
import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;

     
  public class References {  
	  
    public static void main(String[] args) {  
      String weakObj, phantomObj, softObj;  
      Reference<? extends String> ref;  
      WeakReference<String> weakRef;  
      PhantomReference<String> phantomRef;  
      SoftReference<String> softRef;
      ReferenceQueue<String> weakQueue, phantomQueue, softQueue;  
    
       weakObj    = new String("Weak Reference");  
       phantomObj = new String("Phantom Reference");
       softObj = new String("Soft Reference");
       weakQueue    = new ReferenceQueue<String>();  
       phantomQueue = new ReferenceQueue<String>();  
       softQueue = new ReferenceQueue<String>();
       weakRef    = new WeakReference<String>(weakObj, weakQueue);  
       phantomRef = new PhantomReference<String>(phantomObj, phantomQueue);  
       softRef = new SoftReference<String>(softObj, softQueue);
    
       // Print referents to prove they exist   Phantom referents  
       // are inaccessible so we should see a null value   
       System.out.println("Weak Reference: " + weakRef.get());  
       System.out.println("Phantom Reference: " + phantomRef.get());  
       System.out.println("Soft Reference: " + softRef.get());
    
       // Clear all strong references  
       weakObj    = null;  
       phantomObj = null;  
       softObj = null;
    
       // Invoke garbage collector in hopes that references  
       // will be queued  
       System.gc();  
    
       // See if the garbage collector has queued the references  
       System.out.println("Weak Queued: " + weakRef.isEnqueued());  
       // Try to finalize the phantom references if not already  
       if(!phantomRef.isEnqueued()) {  
         System.out.println("Requestion finalization ");  
         System.runFinalization();  
       }  
       System.out.println("Phantom Queued: " + phantomRef.isEnqueued());  
       System.out.println("Soft Queued: " + softRef.isEnqueued()); 
    
       // Wait until the weak reference is on the queue and remove it  
       try {  
         ref = weakQueue.remove();  
         // The referent should be null  
         System.out.println("Weak Reference: " + ref.get());  
         // Wait until the phantom reference is on the queue and remove it  
         ref = phantomQueue.remove();  
         System.out.println("Phantom Reference: " + ref.get());  
         ref = softQueue.remove();  
         System.out.println("Soft Reference: " + ref.get());  
         // We have to clear the phantom referent even though  
         // get() returns null  
         ref.clear();  
       } catch(InterruptedException e) {  
         e.printStackTrace();  
         return;  
       }  
     }  
   }

 出力の結果は次のとおりです.
Weak Reference: Weak Reference
Phantom Reference: null
Soft Reference: Soft Reference
Weak Queued: true
Phantom Queued: true
Soft Queued: false
Weak Reference: null
Phantom Reference: null
 
メモリ領域が十分であれば、ゴミ回収器はソフトリファレンスを回収しません.メモリ領域が不足している場合は、オブジェクトのメモリを回収します.一般的なプログラムはblockがこの文にあります.
ref = softQueue.remove();

 
本明細書は、http://blog.sina.com.cn/s/blog_8417aea80100skwx.htmlに基づいて修正される.