摘要:四種引用類型在中,類型就分為兩種,基本類型和引用類型或自定義類型。軟引用可用來實現內存敏感的高速緩存。一般用法是程序可以通過判斷引用隊列中是否已經加入了虛引用,來了解被引用的對象是否將要被垃圾回收。
Java四種引用類型
在java中,類型就分為兩種,基本類型和引用類型或自定義類型。
引用類型又分為四種:
強引用 StrongReference
軟引用 SoftReference
若引用 WeakReference
虛引用 PhantomReference
劃分這些類型的目的是:是為了更靈活的管理對象的生命周期,讓垃圾器在最合適的時間適合回收對象,常見使用的場景是在緩存的實現,比如elasticsearch在載入數據到緩存時,可以選擇SoftReference作為緩存的生命周期,在對象池組件common-pool中也利用到SoftReference管理對象池的對象生命周期。雖然,我們在實際業務中很少有用到這些知識,但是很有必要了解到這些,去幫助我們去做些程序性能優化。
強引用強引用就是直接引用對象比如下面這樣,我們在編寫程序時,用到的大多都是強引用
StringBuffer b1 = new StringBuffer("hello world");
強引用對象,當垃圾回收進行時,不會被回收,及時通過b1 = null;釋放引用,在資源充足時,也不會被垃圾回收立刻回收。如果內存吃緊,Java虛擬機會拋出OutOfMemoryError錯誤,使程序異常終止,不會靠隨意回收具有強引用的對象來解決內存不足的問題。
軟引用SoftReferencesoftReference = new SoftReference (new StringBuffer("hello world")); System.gc(); System.out.print(softReference.get()); // 只有當內存吃緊時,發生gc后,會報Exception in thread "main" java.lang.NullPointerException,
軟引用的生命周期會比強引用弱點,在內存空間足夠時,垃圾回收器就不會回收它;如果內存空間不足了,就會回收這些對象的內存。只要垃圾回收器沒有回收它,該對象就可以被程序使用。軟引用可用來實現內存敏感的高速緩存。
它也經常和ReferenceQueue配合使用,如果gc在回收掉引用對象后,會把保存引用對象的softReference送入隊列,這時可以通過下面這行代碼判斷是否被回收。
// 創建softReference并提供給注冊隊列 ReferenceQueuereferenceQueue = new ReferenceQueue (); SoftReference softReference = new SoftReference (new StringBuffer("hello world"),referenceQueue); // 判斷入隊列來判斷是否被回收,或直接判斷softReference.get() == null softReference.get() == null || softReference.enqueue()
另外也可以手動清除這些保存引用對象的reference對象
Reference ref; while ((ref = referenceQueue.poll()) != null) { // poll出即清除,也不必手動清除,等待gc清除 }
使用案列:common-pool2的SoftReferenceObjectPool,用于實現一種可以隨著需要而增長的池對象管理,當gc時可以清除空閑的實例。
下面是common-pool2的部分代碼,具體可以參照其里面的SoftReferenceObjectPool類
@Override public synchronized void addObject() throws Exception { assertOpen(); if (factory == null) { throw new IllegalStateException( "Cannot add objects without a factory."); } T obj = factory.makeObject().getObject(); createCount++; // Create and register with the queue PooledSoftReference弱引用ref = new PooledSoftReference ( new SoftReference (obj, refQueue)); allReferences.add(ref); boolean success = true; if (!factory.validateObject(ref)) { success = false; } else { factory.passivateObject(ref); } boolean shouldDestroy = !success; if (success) { idleReferences.add(ref); notifyAll(); // numActive has changed } if (shouldDestroy) { try { destroy(ref); } catch (Exception e) { // ignored } } @Override public synchronized void returnObject(T obj) throws Exception { boolean success = !isClosed(); final PooledSoftReference ref = findReference(obj); if (ref == null) { throw new IllegalStateException( "Returned object not currently part of this pool"); } if (factory != null) { if (!factory.validateObject(ref)) { success = false; } else { try { factory.passivateObject(ref); } catch (Exception e) { success = false; } } } boolean shouldDestroy = !success; numActive--; if (success) { // Deallocate and add to the idle instance pool ref.deallocate(); idleReferences.add(ref); } notifyAll(); // numActive has changed if (shouldDestroy && factory != null) { try { destroy(ref); } catch (Exception e) { // ignored } } }
WeakReferenceweakReference = new WeakReference (new StringBuffer("hello world")); WeakReference weakReference2 = new WeakReference (new StringBuffer("hello world")); System.out.print(weakReference.get()); // hello world StringBuffer buffer = weakReference2.get(); System.gc(); System.out.print(weakReference.get()); // Exception in thread "main" java.lang.NullPointerException System.out.print(weakReference2.get()); // hello world
弱引用會在發生gc時,沒有對象在去引用時會被立刻被回收,不管內存是否充裕。
使用案列:WeakHashMap
虛引用ReferenceQueuestringBufferReferenceQueue = new ReferenceQueue (); PhantomReference phantomReference = new PhantomReference (new StringBuffer("hello world"), stringBufferReferenceQueue); System.out.print(phantomReference.get());Exception in thread "main" java.lang.NullPointerException
虛引用,不顧是否被垃圾回收,都不可以拿到真正的引用對象。一般用法是
程序可以通過判斷引用隊列中是否已經加入了虛引用,來了解被引用的對象是否將要被垃圾回收。如果程序發現某個虛引用已經被加入到引用隊列,那么就可以在所引用的對象的內存被回收之前采取必要的行動。
具體Demo代碼請參照:ReferenceDemo
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/64719.html
摘要:在之后,對引用的概念進行了擴充,將引用分為強引用軟引用弱引用虛引用種,這種引用強度依次逐漸減弱。軟引用是用來描述一些還有用但并非必需的對象。虛引用也稱為幽靈引用或者幻影引用,它是最弱的一種引用關系。 以下內容摘自《深入理解Java虛擬機 JVM高級特性與最佳實踐》第2版,強烈推薦沒有看過的同學閱讀,讀完的感覺就是原來學的都是些什么瘠薄東西(╯‵□′)╯︵┴─┴ 在JDK1.2以前,Ja...
摘要:如果想中斷強引用和某個對象之間的關聯,可以顯式地將引用賦值為,這樣一來的話,在合適的時間就會回收該對象。不過由于垃圾回收器是一個優先級較低的線程,所以并不一定能迅速發現弱引用對象。 強引用,軟引用,弱引用,虛引用。不同的引用類型主要體現在GC上: △強引用:如果一個對象具有強引用,它就不會被垃圾回收器回收。即使當前內存空間不足,JVM也不會回收它,而是拋出 OutOfMemoryErr...
摘要:虛引用與軟引用和弱引用的一個區別在于虛引用必須和引用隊列聯合使用。 本文已同步至個人博客liaosis blog 在Java中是由JVM負責內存的分配和回收,這是它的優點(簡化編程者的工作,不需要像C語言那樣去手動操作內存),但同時也是它的缺點(不夠靈活,垃圾回收對于編程者來說是不可控的)。 在JDK1.2以前,如果一個對象不被任何變量引用,則程序無法再次使用這個對象,這個對象最終會...
摘要:弱引用與軟引用最大的區別就是弱引用比軟引用的生命周期更短暫。所以對于軟引用弱引用之類,垃圾收集器可能會存在二次確認的問題,以確保處于弱引用狀態的對象沒有改變為強引用。 關于強引用、軟引用、弱引用、幻象引用的區別,在一些大公司的面試題中經常出現,可能有些小伙伴覺得這個知識點比較冷門,但其實大家在開發中經常用到,如new一個對象的時候就是強引用的應用。 在java語言中,除了原始數據類型(...
閱讀 639·2021-08-17 10:15
閱讀 1717·2021-07-30 14:57
閱讀 1976·2019-08-30 15:55
閱讀 2815·2019-08-30 15:55
閱讀 2707·2019-08-30 15:44
閱讀 669·2019-08-30 14:13
閱讀 2384·2019-08-30 13:55
閱讀 2590·2019-08-26 13:56