標籤:
***********************************************聲明******************************************************
原創作品,出自 “曉風殘月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強引用、軟引用、弱引用、虛引用詳解