虛引用在垃圾回收時候,搶救不了了。對象回收的時候直接回收,若是用ReferenceQueue,那麼在回收時候經過這個隊列,能夠人爲作些處理。軟引用弱引用先置位referent爲null回收堆內存,而後把虛引用對象加入隊列,最後在隊列裏面回收虛引用對象。java
虛引用必需要和ReferenceQueue結合使用,軟引用弱引用能夠不和ReferenceQueue結合使用。程序員
強引用 : 就是普通的引用. 內存不足拋 Out of Memory 異常jvm
軟引用(SoftReferenve) : 內存充足的狀況下不會被回收,內存不充足的狀況下才會被回收。可以很好地規避OOM異常。函數
弱引用(WeakReference) : 當垃圾回收機制運行時, 弱引用引用的對象就會被回收掉.this
// 新建一個引用隊列spa
ReferenceQueue<TestObject> referenceQueue = new ReferenceQueue<>();code
// 創建一個TestObject的弱引用對象
SoftReference<TestObject> reference = new SoftReference<>(new TestObject(), referenceQueue)blog
弱引用和軟引用在建立的時候均可以傳進去一個引用隊列(固然也能夠不使用引用隊列), 當弱引用和軟引用引用的對象須要進行回收的時候, JVM都是先將其referent字段設置成null,以後將軟引用或弱引用對象自己,加入到關聯的引用隊列中。也就是說JVM先回收堆對象內存,而後纔將軟引用或弱引用自己加入到引用隊列。隊列
// 建立一個引用隊列
ReferenceQueue<TestObject> referenceQueue = new ReferenceQueue<>();
PhantomReference reference = new PhantomReference<>(new TestObject(), referenceQueue);
而虛引用(PhantomReference) 不一樣, 他必須和引用隊列 (ReferenceQueue)聯合使用, 若GC啓動時, 則將引用對象傳到它的引用隊列中去. 可是不會將虛引用的referent字段設置成null, 也就是不會釋放虛引用指向的TestObject的堆對象內存空間。
若是虛引用引用的對象重寫了finalize方法, 在虛引用對象傳到它的引用隊列以前還會調用對象的finalize方法, 可是調用以後內存不會回收.
你能夠經過手動調用PhantomReference.clear()方法來釋放虛引用指向的的堆對象內存空間。
虛引用的存在更傾向於實現程序員對內存回收的細粒度性控制, 當虛引用肯定會被回收以後, 會嚮應用程序發送通知, 此時程序員進行對內存清理的細微操做.
public static void main(String[] args) { Object obj = new Object(); ReferenceQueue<Object> refQueue = new ReferenceQueue<Object>(); WeakReference<Object> weakRef = new WeakReference<Object>(obj, refQueue); System.out.println(weakRef.get());//返回weakRef裏面的obj System.out.println(refQueue.poll());//隊列滅有元素 obj = null;//只有weakRef 指向new Object()內存,不置位null,gc時候不會將weakRef 的eferent被置位了null,也不會將weakRef加入refQueue隊列 System.gc(); System.gc(); System.gc(); System.gc();//System.gc()是告訴JVM這是一個執行GC的好時機,但具體執不執行由JVM決定, System.out.println(weakRef.get());//referent被置位了null System.out.println(refQueue.poll());//隊列裏面有一個元素weakRef可是weakRef的referent被置位了null }
public class Test0009 { public static void main(String[] args) throws InterruptedException { Object obj = new Object(); ReferenceQueue<Object> refQueue = new ReferenceQueue<Object>(); PhantomReference<Object> phanRef = new PhantomReference<Object>(obj, refQueue); System.out.println(phanRef.get());//null,phanRef裏面有元素可是一直返回null,由於PhantomReference重寫了Reference的get方法,寫死了返回null。 System.out.println(refQueue.poll());//隊列爲空, obj = null;//不置位null,phanRef裏面有元素,隊列爲空。 System.gc(); System.gc(); System.gc(); System.out.println(phanRef.get());//phanRef裏面仍然有元素,referent並無像弱引用軟引用那樣置位空, System.out.println(refQueue.poll());//隊列有元素, } }
class Registry { private Set registeredObjects = new HashSet(); public void register(Object object) { registeredObjects.add( object ); } } 全部我添加進 registeredObjects 中的object永遠不會被GC回收,由於這裏有個強引用保存在registeredObjects裏,
object 內存對象被2個強引用關聯。另外一方面若是我把代碼改成以下:
class Registry { private Set registeredObjects = new HashSet(); public void register(Object object) { registeredObjects.add( new WeakReference(object) ); } } 如今若是GC想要回收registeredObjects中的object,object 內存對象被1個強引用1個弱引用關聯,便可以實現了,
一樣在使用HashMap若是想實現如上的效果,一種更好的實現是使用WeakHashMap
強引用:一直不回收
軟引用:內存不足回收
弱引用:gc就回收
虛引用: 「虛引用」顧名思義,就是形同虛設,一個對象僅持有虛引用,那麼它就和沒有任何引用同樣。虛引用主要用來跟蹤對象被垃圾回收器回收的活動。虛引用必須和引用隊列 (ReferenceQueue)聯合使用。
當垃圾回收器準備回收一個對象時,若是發現它還有虛引用,就會在回收對象的內存以前,把這個虛引用加入到與之 關聯的引用隊列中。
虛引用裏面的對象沒有強引用時候,開始回收,加入到隊列去,並不會置referent爲null。
軟引用弱引用裏面的對象沒有強引用時候,開始回收,加入到隊列去,置referent爲null。
public class MyDate extends Date { /** Creates a new instance of MyDate */ public MyDate() { } // 覆蓋finalize()方法,finalize()函數是在JVM回收內存時執行的, protected void finalize() throws Throwable { super.finalize(); System.out.println("obj [Date: " + this.getTime() + "] is gc"); } public String toString() { return "Date: " + this.getTime(); } }
虛引用也稱爲幽靈引用或者幻影引用,它是最弱的一種引用關係。一個僅僅持有虛引用的對象,和沒有引用幾乎是同樣的,隨時都有可能被垃圾回收器回收。當試圖經過虛引用的get()方法取得強引用時,老是會失敗。而且,虛引用必須和引用隊列一塊兒使用,它的做用在於跟蹤垃圾回收過程。
當你的虛引用所引用的對象已經執行完finalize函數的時候,就會把對象加到queue裏面。
-Xmx的值是新生代和老生代的和的最大值,-XX:MaxPermSize來指定持久代的最大值,Java堆的最大值實際上是-Xmx和-XX:MaxPermSize的總和。
那麼剩下的均可以認爲是堆外內存(廣義的)了,這些包括了jvm自己在運行過程當中分配的內存,codecache,jni裏分配的內存,DirectByteBuffer分配的內存等等。
這個主要是指java.nio.DirectByteBuffer在建立的時候分配內存。/