Java強引用、ソフト引用、弱引用、虚引用の詳細

10200 ワード

************************************************************************************************声明を出して********を**します。
      オリジナル作品は、「暁風残月xj」のブログから来ました。転載を歓迎します。転載する時は必ず出典を明記してください。http://blog.csdn.net/xiaofengcanyuexjを選択します
      様々な原因のため、多くの不足があるかもしれません。斧を歓迎します。
**********
******************************************************************************************
       Javaにはポインターの概念がなく、参照は弱化のポインターであり、開発が任意にメモリを操作できないことを保証する。最近はよく分からないレベルの引用を整理しました。強引用、ソフト引用、弱引用、虚引用、それらの特徴と応用シーンは以下のようにまとめられています。
1、強引用    強い引用がある場合、GCはそれを回収しません。メモリの空間が足りない時、JVMはむしろOutOfMemoryErrエラーを投げます。一般的にnewの対象は強い引用です。以下の通りです。
//   
User strangeReference=new User();
      
2、ソフト引用     オブジェクトがソフト参照を持っている場合、メモリ空間が足りない場合、GCはこれらのオブジェクトのメモリを回収し、ソフト参照を使用して敏感データのキャッシュを構築する。
     JVMではソフト引用は以下のように定義されています。タイムスタンプで回収できます。以下はJVMから引用します。
public class SoftReference<T> extends Reference<T> {

    /**
     * Timestamp clock, updated by the garbage collector
     */
    static private long clock;

    /**
     * Timestamp updated by each invocation of the get method.  The VM may use
     * this field when selecting soft references to be cleared, but it is not
     * required to do so.
     */
    private long timestamp;

    /**
     * Creates a new soft reference that refers to the given object.  The new
     * reference is not registered with any queue.
     *
     * @param referent object the new soft reference will refer to
     */
    public SoftReference(T referent) {
        super(referent);
        this.timestamp = clock;
    }

    /**
     * Creates a new soft reference that refers to the given object and is
     * registered with the given queue.
     *
     * @param referent object the new soft reference will refer to
     * @param q the queue with which the reference is to be registered,
     *          or <tt>null</tt> if registration is not required
     *
     */
    public SoftReference(T referent, ReferenceQueue<? super T> q) {
        super(referent, q);
        this.timestamp = clock;
    }

    /**
     * Returns this reference object's referent.  If this reference object has
     * been cleared, either by the program or by the garbage collector, then
     * this method returns <code>null</code>.
     *
     * @return   The object to which this reference refers, or
     *           <code>null</code> if this reference object has been cleared
     */
    public T get() {
        T o = super.get();
        if (o != null && this.timestamp != clock)
            this.timestamp = clock;
        return o;
    }

}
  
 ソフト引用の声明は強い引用または匿名の対象によって、汎型ソフトReference<T>を使用する。get法により強い参照が得られます。具体的には以下の通りです
//   
SoftReference<User>softReference=new SoftReference<User>(new User());
strangeReference=softReference.get();//  get       
3、弱引用        オブジェクトが弱い参照を持っている場合、GCスレッドがメモリ領域をスキャンする過程で、現在のメモリ空間が十分であるかどうかにかかわらず、メモリを回収し、弱い参照を使って非敏感データのキャッシュを構築する。
     JVMでは弱引用は以下のように定義されており、以下はJVMから引用される。
public class WeakReference<T> extends Reference<T> {

    /**
     * Creates a new weak reference that refers to the given object.  The new
     * reference is not registered with any queue.
     *
     * @param referent object the new weak reference will refer to
     */
    public WeakReference(T referent) {
        super(referent);
    }

    /**
     * Creates a new weak reference that refers to the given object and is
     * registered with the given queue.
     *
     * @param referent object the new weak reference will refer to
     * @param q the queue with which the reference is to be registered,
     *          or <tt>null</tt> if registration is not required
     */
    public WeakReference(T referent, ReferenceQueue<? super T> q) {
        super(referent, q);
    }

}
    弱い引用の声明は強い引用または匿名の対象によって汎型WeakReference<T>を使用しており、具体的には以下の通りである。
//   
WeakReference<User>weakReference=new WeakReference<User>(new User());
4、虚引用     もし一つの対象が虚引用だけを持っていれば、いつでもゴミに回収されます。虚引用とソフト引用と弱引用の違いは、虚引用は必ず列と連携して使用します。虚引用は主に対象のゴミ回収活動を追跡します。
     JVMにおいて、虚引用は以下のように定義されており、以下はJVMから引用される。
public class PhantomReference<T> extends Reference<T> {

    /**
     * Returns this reference object's referent.  Because the referent of a
     * phantom reference is always inaccessible, this method always returns
     * <code>null</code>.
     *
     * @return  <code>null</code>
     */
    public T get() {
        return null;
    }

    /**
     * Creates a new phantom reference that refers to the given object and
     * is registered with the given queue.
     *
     * <p> It is possible to create a phantom reference with a <tt>null</tt>
     * queue, but such a reference is completely useless: Its <tt>get</tt>
     * method will always return null and, since it does not have a queue, it
     * will never be enqueued.
     *
     * @param referent the object the new phantom reference will refer to
     * @param q the queue with which the reference is to be registered,
     *          or <tt>null</tt> if registration is not required
     */
    public PhantomReference(T referent, ReferenceQueue<? super T> q) {
        super(referent, q);
    }

}
     
PhotomReference<T>の声明を引用することは、強引用または匿名の対象によって、汎型ReferenceQue<T>を初期化し、具体的には以下の通りである。
//   
PhantomReference<User> phantomReference=new PhantomReference<User>(new User(),new ReferenceQueue<User>());
5、まとめ
  強引用、ソフト引用、弱引用、虚引用に関する手順は以下の通りです。
import java.lang.ref.*;
import java.util.HashSet;
import java.util.Set;

class User {

    private String name;

    public User()
    {}

    public User(String name)
    {
        this.name=name;
    }

    @Override
    public String toString() {
        return name;
    }

    public void finalize(){
        System.out.println("Finalizing ... "+name);
    }
}

/**
 * Created by jinxu on 15-4-25.
 */
public class ReferenceDemo {

    private static ReferenceQueue<User> referenceQueue = new ReferenceQueue<User>();
    private static final int size = 10;

    public static void checkQueue(){
       /* Reference<? extends User> reference = null;
        while((reference = referenceQueue.poll())!=null){
            System.out.println("In queue : "+reference.get());
        }*/
        Reference<? extends User> reference = referenceQueue.poll();
        if(reference!=null){
            System.out.println("In queue : "+reference.get());
        }
    }

    public static void testSoftReference()
    {
        Set<SoftReference<User>> softReferenceSet = new HashSet<SoftReference<User>>();
        for (int i = 0; i < size; i++) {
            SoftReference<User> ref = new SoftReference<User>(new User("Soft " + i), referenceQueue);
            System.out.println("Just created: " + ref.get());
            softReferenceSet.add(ref);
        }
        System.gc();
        checkQueue();
    }

    public static void testWeaKReference()
    {
        Set<WeakReference<User>> weakReferenceSet = new HashSet<WeakReference<User>>();
        for (int i = 0; i < size; i++) {
            WeakReference<User> ref = new WeakReference<User>(new User("Weak " + i), referenceQueue);
            System.out.println("Just created: " + ref.get());
            weakReferenceSet.add(ref);
        }
        System.gc();
        checkQueue();
    }

    public static void testPhantomReference()
    {
        Set<PhantomReference<User>> phantomReferenceSet = new HashSet<PhantomReference<User>>();
        for (int i = 0; i < size; i++) {
            PhantomReference<User> ref =
                    new PhantomReference<User>(new User("Phantom " + i), referenceQueue);
            System.out.println("Just created: " + ref.get());
            phantomReferenceSet.add(ref);
        }
        System.gc();
        checkQueue();
    }

    public static void main(String[] args) {
        testSoftReference();
        testWeaKReference();
        testPhantomReference();
    }
}
     結果は
Just created: Soft 0
Just created: Soft 1
Just created: Soft 2
Just created: Soft 3
Just created: Soft 4
Just created: Soft 5
Just created: Soft 6
Just created: Soft 7
Just created: Soft 8
Just created: Soft 9
Just created: Weak 0
Just created: Weak 1
Just created: Weak 2
Just created: Weak 3
Just created: Weak 4
Just created: Weak 5
Just created: Weak 6
Just created: Weak 7
Just created: Weak 8
Just created: Weak 9
Finalizing ... Weak 7
Finalizing ... Weak 8
Finalizing ... Weak 9
Finalizing ... Weak 4
Finalizing ... Weak 5
Finalizing ... Weak 6
Finalizing ... Weak 0
Finalizing ... Weak 1
Finalizing ... Weak 2
Finalizing ... Weak 3
Finalizing ... Soft 9
Finalizing ... Soft 8
Finalizing ... Soft 7
Finalizing ... Soft 6
Finalizing ... Soft 5
Finalizing ... Soft 4
Finalizing ... Soft 3
Finalizing ... Soft 2
Finalizing ... Soft 1
Finalizing ... Soft 0
In queue : null
Just created: null
Just created: null
Just created: null
Just created: null
Just created: null
Just created: null
Just created: null
Just created: null
Just created: null
Just created: null
In queue : null
Finalizing ... Phantom 9
Finalizing ... Phantom 7
Finalizing ... Phantom 8
Finalizing ... Phantom 4
Finalizing ... Phantom 5
Finalizing ... Phantom 6
Finalizing ... Phantom 0
Finalizing ... Phantom 1
Finalizing ... Phantom 2
Finalizing ... Phantom 3
     プログラムの実行結果から、虚引用は虚構のように見えます。参照対象はいつでもごみ箱に回収され、弱い引用の対象は少し長いライフサイクルを持っています。ごみ箱が回収操作を実行すると、ごみ箱に回収される可能性があります。ソフト参照の対象はより長いライフサイクルを持っています。しかし、Java仮想マシンではメモリが足りないと判断した場合、ゴミ回収機に回収されます。
         時間が限られているので、ブログを書いている間に文献を参考にしました。ありがとうございます。同時にレベルの原因にかんがみて、どうしても足りないところがあります。斧を歓迎します。