周全解析Java中的GC與鬼魂援用。本站提示廣大學習愛好者:(周全解析Java中的GC與鬼魂援用)文章只能為提供參考,不一定能成為您想要的結果。以下是周全解析Java中的GC與鬼魂援用正文
Java 中一共有 4 品種型的援用 : StrongReference、 SoftReference、 WeakReference 和 PhantomReference (傳說中的鬼魂援用 呵呵),
這 4 品種型的援用與 GC 有著親密的關系, 讓我們一一來看它們的界說和應用場景 :
1、 Strong Reference
StrongReference 是 Java 的默許援用完成, 它會盡量長時光的存活於 JVM 內, 當沒有任何對象指向它時 GC 履行後將會被收受接管
Java代碼
@Test
public void strongReference() {
Object referent = new Object();
/**
* 經由過程賦值創立 StrongReference
*/
Object strongReference = referent;
assertSame(referent, strongReference);
referent = null;
System.gc();
/**
* StrongReference 在 GC 後不會被收受接管
*/
assertNotNull(strongReference);
}
2、 WeakReference & WeakHashMap
WeakReference, 望文生義, 是一個弱援用, 當所援用的對象在 JVM 內不再有強援用時, GC 後 weak reference 將會被主動收受接管
@Test
public void weakReference() {
Object referent = new Object();
WeakReference<Object> weakRerference = new WeakReference<Object>(referent);
assertSame(referent, weakRerference.get());
referent = null;
System.gc();
/**
* 一旦沒有指向 referent 的強援用, weak reference 在 GC 後會被主動收受接管
*/
assertNull(weakRerference.get());
}
WeakHashMap 應用 WeakReference 作為 key, 一旦沒有指向 key 的強援用, WeakHashMap 在 GC 後將主動刪除相干的 entry
@Test
public void weakHashMap() throws InterruptedException {
Map<Object, Object> weakHashMap = new WeakHashMap<Object, Object>();
Object key = new Object();
Object value = new Object();
weakHashMap.put(key, value);
assertTrue(weakHashMap.containsValue(value));
key = null;
System.gc();
/**
* 期待有效 entries 進入 ReferenceQueue 以便下一次挪用 getTable 時被清算
*/
Thread.sleep(1000);
/**
* 一旦沒有指向 key 的強援用, WeakHashMap 在 GC 後將主動刪除相干的 entry
*/
assertFalse(weakHashMap.containsValue(value));
}
3、SoftReference
SoftReference 於 WeakReference 的特征根本分歧, 最年夜的差別在於 SoftReference 會盡量長的保存援用直到 JVM 內存缺乏時才會被收受接管(虛擬機包管), 這一特征使得 SoftReference 異常合適緩存運用
@Test
public void softReference() {
Object referent = new Object();
SoftReference<Object> softRerference = new SoftReference<Object>(referent);
assertNotNull(softRerference.get());
referent = null;
System.gc();
/**
* soft references 只要在 jvm OutOfMemory 之前才會被收受接管, 所以它異常合適緩存運用
*/
assertNotNull(softRerference.get());
}
4、 PhantomReference
作為本文配角, Phantom Reference(鬼魂援用) 與 WeakReference 和 SoftReference 有很年夜的分歧, 由於它的 get() 辦法永久前往 null, 這也恰是它名字的由來
Java代碼
@Test
public void phantomReferenceAlwaysNull() {
Object referent = new Object();
PhantomReference<Object> phantomReference = new PhantomReference<Object>(referent, new ReferenceQueue<Object>());
/**
* phantom reference 的 get 辦法永久前往 null
*/
assertNull(phantomReference.get());
}
諸位能夠要問, 一個永久前往 null 的 reference 要來何用, 請留意結構 PhantomReference 時的第二個參數 ReferenceQueue(現實上 WeakReference & SoftReference 也能夠有這個參數),
PhantomReference 獨一的用途就是跟蹤 referent 什麼時候被 enqueue 到 ReferenceQueue 中.
5、 RererenceQueue
當一個 WeakReference 開端前往 null 時, 它所指向的對象曾經預備被收受接管, 這時候可以做一些適合的清算任務. 將一個 ReferenceQueue 傳給一個 Reference 的結構函數, 當對象被收受接管時, 虛擬機遇主動將這個對象拔出到 ReferenceQueue 中, WeakHashMap 就是應用 ReferenceQueue 來消除 key 曾經沒有強援用的 entries.
Java代碼
@Test
public void referenceQueue() throws InterruptedException {
Object referent = new Object();
ReferenceQueue<Object> referenceQueue = new ReferenceQueue<Object>();
WeakReference<Object> weakReference = new WeakReference<Object>(referent, referenceQueue);
assertFalse(weakReference.isEnqueued());
Reference<? extends Object> polled = referenceQueue.poll();
assertNull(polled);
referent = null;
System.gc();
assertTrue(weakReference.isEnqueued());
Reference<? extends Object> removed = referenceQueue.remove();
assertNotNull(removed);
}
6、PhantomReference vs WeakReference
PhantomReference 有兩個利益, 其一, 它可讓我們精確地曉得對象什麼時候被從內存中刪除, 這個特征可以被用於一些特別的需求中(例如 Distributed GC, XWork 和 谷歌-guice 中也應用 PhantomReference 做了一些清算性任務).
其二, 它可以免 finalization 帶來的一些基本性成績, 上文提到 PhantomReference 的獨一感化就是跟蹤 referent 什麼時候被 enqueue 到 ReferenceQueue 中, 然則 WeakReference 也有對應的功效, 二者的差別究竟在哪呢 ?
這就要說到 Object 的 finalize 辦法, 此辦法將在 gc 履行前被挪用, 假如某個對象重載了 finalize 辦法並有意在辦法內創立自己的強援用, 這將招致這一輪的 GC 沒法收受接管這個對象並有能夠惹起隨意率性次 GC, 最初的成果就是明明 JVM 內有許多 Garbage 卻 OutOfMemory, 應用 PhantomReference 便可以免這個成績, 由於 PhantomReference 是在 finalize 辦法履行後收受接管的,也就意味著此時曾經弗成能拿到本來的援用, 也就不會湧現上述成績, 固然這是一個很極真個例子, 普通不會湧現.
7、 比較
Soft vs Weak vs Phantom References
Type
Purpose
Use
When GCed
Implementing Class
Strong Reference
An ordinary reference. Keeps objects alive as long as they are referenced.
normal reference.
Any object not pointed to can be reclaimed.
default
Soft Reference
Keeps objects alive provided there's enough memory.
to keep objects alive even after clients have removed their references (memory-sensitive caches), in case clients start asking for them again by key.
After a first gc pass, the JVM decides it still needs to reclaim more space.
java.lang.ref.SoftReference
Weak Reference
Keeps objects alive only while they're in use (reachable) by clients.
Containers that automatically delete objects no longer in use.
After gc determines the object is only weakly reachable
java.lang.ref.WeakReference
java.util.WeakHashMap
Phantom Reference
Lets you clean up after finalization but before the space is reclaimed (replaces or augments the use offinalize())
Special clean up processing
After finalization.
java.lang.ref.PhantomReference
8. 小結
普通的運用法式不會觸及到 Reference 編程, 然則懂得這些常識會對懂得 GC 的任務道理和機能調優有必定贊助,在完成一些基本性舉措措施好比緩存時也能夠會用到, 願望本文能有所贊助。