Java強引用、軟引用、弱引用、虛引用詳解

來源:互聯網
上載者:User

標籤:


***********************************************聲明***********************
*******************************

      原創作品,出自 “曉風殘月xj” 部落格,歡迎轉載,轉載時請務必註明出處(http://blog.csdn.net/xiaofengcanyuexj)。

      由於各種原因,可能存在諸多不足,歡迎斧正!

*************** ******************************************************************************************

       Java中沒有指標的概念,而引用就是一個弱化的指標,保證開發不能任意操作記憶體。最近整理了一下之前不明白的各種層級引用:強引用、軟引用、弱引用、虛引用,它們的特點和應用情境匯總如下:

1、強引用
    如果一個對象具有強引用,GC絕不會回收它;當記憶體空間不足,JVM寧願拋出OutOfMemoryError錯誤。一般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;    }}
   軟引用的聲明的藉助強引用或者匿名對象,使用泛型SoftReference<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);    }}
     虛引用PhantomReference<T>的聲明的藉助強引用或者匿名對象,結合泛型ReferenceQueue<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 0Just created: Soft 1Just created: Soft 2Just created: Soft 3Just created: Soft 4Just created: Soft 5Just created: Soft 6Just created: Soft 7Just created: Soft 8Just created: Soft 9Just created: Weak 0Just created: Weak 1Just created: Weak 2Just created: Weak 3Just created: Weak 4Just created: Weak 5Just created: Weak 6Just created: Weak 7Just created: Weak 8Just created: Weak 9Finalizing ... Weak 7Finalizing ... Weak 8Finalizing ... Weak 9Finalizing ... Weak 4Finalizing ... Weak 5Finalizing ... Weak 6Finalizing ... Weak 0Finalizing ... Weak 1Finalizing ... Weak 2Finalizing ... Weak 3Finalizing ... Soft 9Finalizing ... Soft 8Finalizing ... Soft 7Finalizing ... Soft 6Finalizing ... Soft 5Finalizing ... Soft 4Finalizing ... Soft 3Finalizing ... Soft 2Finalizing ... Soft 1Finalizing ... Soft 0In queue : nullJust created: nullJust created: nullJust created: nullJust created: nullJust created: nullJust created: nullJust created: nullJust created: nullJust created: nullJust created: nullIn queue : nullFinalizing ... Phantom 9Finalizing ... Phantom 7Finalizing ... Phantom 8Finalizing ... Phantom 4Finalizing ... Phantom 5Finalizing ... Phantom 6Finalizing ... Phantom 0Finalizing ... Phantom 1Finalizing ... Phantom 2Finalizing ... Phantom 3


     從程式運行結果可以看出,虛引用形同虛設,它所引用的對象隨時可能被記憶體回收行程回收,具有弱引用的對象擁有稍微長一點的生命週期,當記憶體回收行程執行回收操作時,有可能被記憶體回收行程回收,具有軟引用的對象擁有更長的生命週期,但在Java虛擬機器認為記憶體不足的情況下,也是會被記憶體回收行程回收的。


         由於時間有限,在寫博文的過程中參考過一些文獻,在此表示感謝;同時鑒於水平原因,你難免有不足之處,歡迎斧正!

Java強引用、軟引用、弱引用、虛引用詳解

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.