首頁  >  文章  >  Java  >  Java開發中的強引用、軟引用、弱引用、虛引用

Java開發中的強引用、軟引用、弱引用、虛引用

无忌哥哥
无忌哥哥原創
2018-07-23 10:05:431447瀏覽

Java由於有GC自動回收機制,所以在引用數數這塊的機制相對完善,Java將持有物件的參考依照強弱順序分成:強引用、軟引用、弱引用、虛引用,引用使用得好可以讓GC快速回收已經超過生命週期的實例,使機器的內存佔用處於一個動態較低的水平,使用不當就會產生內存洩漏,導致機器內存消耗殆盡,宕機,我們要清楚的掌控自己寫的程式的特性,要讓程式處於可控的狀態,至少是目前認為可控的。下面我們先來了解下引用的分類,再去探究使用的場景。

1、強引用

我們平常使用的就是強引用,如:

Map<String, Object> param = new HashMap<String, Object>(16);

形如上述的引用就是強引用了,只要引用還在在有效生命週期內,GC就無法將引用對應的堆上的空間回收,當然引用本身也是無法回收的,強引用的使用和規則是不言而喻的。

2、軟引用

先來看看軟引用的使用方式:

Map<String, Object> param = new HashMap<String, Object>(16);
param.put("status", 1);
SoftReference> softRef = new SoftReference>(param);
System.out.println(softRef.get().get("status"));

使用方式多了一層,但是也好理解,軟引用引用力度僅次於強引用的一種引用,只有在虛擬機器認為記憶體不夠時,軟引用的引用即使還在生命週期內,軟引用指向的堆空間依然被強行回收,這時調用get()返回的就是null ,所以正常情況下,軟引用的表現和強引用無異,只有在虛擬機器認為內存吃緊的時候,軟引用才會體現出他的特性。

3、弱引用

弱引用的使用方式:

Map<String, Object> param = new HashMap<String, Object>(16);
param.put("status", 1);
WeakReference> weakRef = new WeakReference>(param);
System.out.println(weakRef.get().get("status"));

弱引用的使用方式和軟引用幾乎一樣,他是引用力度次於軟引用的一種引用,弱引用對實例的引用不會被引用計數器計算在內,所以如果一個實例沒有強引用的存在,只有弱引用的存在,他有可能返回null,取決於GC有沒有進行回收,上述例子同時存在強引用和弱引用,我們來看下只存在弱引用的情況:

WeakReference<Map<String, Object>> weakRef = new WeakReference<Map<String, Object>>(new HashMap<String, Object>(16));
System.gc();
System.out.println(weakRef.get());

這時印出來的時null,也就是說弱引用不對GC的引用技術有效,使用時注意這個特性。

4、虛引用

虛引用的使用方式和上面略有不同,當GC準備回收一個物件時,如果發現他還有虛引用,就會將這個虛引用加入到與之關聯的引用隊列中。 《深入理解Java虛擬機:JVM高階特性與最佳實務》第二版第3.2.3小節是有這麼一段話,「虛擬引用也稱為幽靈引用或幻影引用,它是最弱的一種引用關係。一個物件是否有虛引用的存在,完全不會對其生存時間構成影響,也無法透過虛引用來取得一個物件實例。為一個物件設定虛引用關聯的唯一目的就是能在這個物件被收集器回收時收到一個系統通知。在JDK 1.2之後,提供了PhantomReference類別來實現虛引用”

我們先來看看虛引用類型的定義:

public class PhantomReference<T> extends Reference<T> {

    public T get() {
        return null;
    }

    public PhantomReference(T referent, ReferenceQueue<? super T> q) {
        super(referent, q);
    }

}

我們看到他只有一個建構函數,而要指定一個引用佇列,下面的程式碼展示了一個Demo:

ReferenceQueue<Map<String, Object>> q = new ReferenceQueue<Map<String, Object>>();
PhantomReference<Map<String, Object>> phantomRef = new PhantomReference<Map<String, Object>>(new HashMap<String, Object>(16), q);
System.gc();
Thread.sleep(1000);
System.out.println(phantomRef.get());
System.out.println(q.poll());

列印結果是null和PhantomReference的一個實例,驗證了無法透過虛引用來取得一個物件實例和參考被加入到引用隊列的事實。

以上是Java開發中的強引用、軟引用、弱引用、虛引用的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn