天天看點

Java中的四種引用

實際上,Java中存在四種引用,它們由強到弱依次是:強引用、軟引用、弱引用、虛引用。下面我們簡單介紹下這四種引用: 

強引用(Strong Reference):通常我們通過new來建立一個新對象時傳回的引用就是一個強引用,若一個對象通過一系列強引用可到達,它就是強可達的(strongly reachable),那麼它就不被回收

軟引用(Soft Reference):軟引用和弱引用的差別在于,若一個對象是弱引用可達,無論目前記憶體是否充足它都會被回收,而軟引用可達的對象在記憶體不充足時才會被回收,是以軟引用要比弱引用“強”一些 

弱引用(Weak Reference):假設垃圾收集器在某個時間點決定一個對象是弱可達的(weakly reachable)(也就是說目前指向它的全都是弱引用),這時垃圾收集器會清除所有指向該對象的弱引用,然後把這個弱可達對象标記為可終結(finalizable)的,這樣它随後就會被回收。與此同時或稍後,垃圾收集器會把那些剛清除的弱引用放入建立弱引用對象時所指定的引用隊列(Reference Queue)中。

虛引用(Phantom Reference):虛引用是Java中最弱的引用,那麼它弱到什麼程度呢?它是如此脆弱以至于我們通過虛引用甚至無法擷取到被引用的對象,虛引用存在的唯一作用就是當它指向的對象被回收後,虛引用本身會被加入到引用隊列中,用作記錄它指向的對象已被回收。 

強引用就是指在程式代碼之中普遍存在的,比如下面這段代碼中的object和str都是強引用:

隻要某個對象有強引用與之關聯,JVM必定不會回收這個對象,即使在記憶體不足的情況下,JVM甯願抛出OutOfMemory錯誤也不會回收這種對象。比如下面這段代碼:

當運作至Object[] objArr = new Object[100000];這句時,如果記憶體不足,JVM會抛出OOM錯誤也不會回收object指向的對象。不過要注意的是,當fun1運作完之後,object和objArr都已經不存在了,是以它們指向的對象都會被JVM回收。

在一個方法fun1的内部有一個強引用object,這個引用儲存在棧中,而真正的引用内容(new Object)儲存在堆中。當這個方法運作完成後就會退出方法棧,則引用内容的引用object不存在,這個new Object會被回收。但是如果這個object是全局的變量時,就需要在不用這個對象時指派為null,因為強引用不會被垃圾回收。

強引用在實際中有非常重要的用處,舉個ArrayList的實作源代碼:

在ArrayList類中定義了一個私有的變量elementData數組,在調用方法清空數組時可以看到為每個數組内容指派為null。不同于elementData=null,elementData強引用仍然存在,避免在後續調用 add()等方法添加元素時進行重新的記憶體配置設定。使用如clear()方法中釋放記憶體的方法對數組中存放的引用類型特别适用,這樣就可以及時釋放記憶體。

  軟引用是用來描述一些有用但并不是必需的對象,在Java中用java.lang.ref.SoftReference類來表示。對于軟引用關聯着的對象,隻有在記憶體不足的時候JVM才會回收該對象。是以,這一點可以很好地用來解決OOM的問題,并且這個特性很适合用來實作緩存,可用來實作記憶體敏感的高速緩存:比如網頁緩存、圖檔緩存等。

  軟引用可以和一個引用隊列(ReferenceQueue)聯合使用,如果軟引用所引用的對象被JVM回收,這個軟引用就會被加入到與之關聯的引用隊列中。下面是一個使用示例:

 軟引用可以和一個引用隊列(ReferenceQueue)聯合使用,如果軟引用所引用的對象被垃圾回收器回收,Java虛拟機就會把這個軟引用加入到與之關聯的引用隊列中。

  假如有一個應用需要讀取大量的本地圖檔,如果每次讀取圖檔都從硬碟讀取,則會嚴重影響性能,但是如果全部加載到記憶體當中,又有可能造成記憶體溢出,此時使用軟引用可以解決這個問題。

  設計思路是:用一個HashMap來儲存圖檔的路徑和相應圖檔對象關聯的軟引用之間的映射關系,在記憶體不足時,JVM會自動回收這些緩存圖檔對象所占用的空間,進而有效地避免了OOM的問題。

弱引用也是用來描述非必需對象的,當JVM進行垃圾回收時,無論記憶體是否充足,都會回收被弱引用關聯的對象。在java中,用java.lang.ref.WeakReference類來表示。

  虛引用和前面的軟引用、弱引用不同,它并不影響對象的生命周期。在java中用java.lang.ref.PhantomReference類表示。如果一個對象與虛引用關聯,則跟沒有引用與之關聯一樣,在任何時候都可能被垃圾回收器回收。

  要注意的是,虛引用必須和引用隊列關聯使用,當垃圾回收器準備回收一個對象時,如果發現它還有虛引用,就會把這個虛引用加入到與之關聯的引用隊列中。程式可以通過判斷引用隊列中是否已經加入了虛引用,來了解被引用的對象是否将要被垃圾回收。如果程式發現某個虛引用已經被加入到引用隊列,那麼就可以在所引用的對象的記憶體被回收之前采取必要的行動。

上一篇: AngularJS API
下一篇: AngularJS 包含