- 通常來講,全部指向對象的引用都已失效,不可能再有程序能調用到這個對象,那麼這個對象就成了垃圾,應該被回收。
- 根據這個思路,很容易就能想到用《引用計數》的辦法來肯定一個對象是不是垃圾。即每當多一個引用指向對象時,引用計數加一,每當少一個引用指向對象時,引用計數減一,引用計數減到零,對象就能夠被回收了。
- 然而引用計數有一個致命問題很差解決,就是循環引用的問題。好比說一個循環鏈表,他們循環引用者,引用計數永遠不會爲零,可是實際上程序已經不能訪問他們了,他們應該被回收。(若是還沒明白循環引用,第五步以後有代碼說明)
- 因此Java其實是使用基於GC Roots的可達性分析,什麼是GC Roots?全部類的靜態變量,每一個線程調用棧上的本地變量(實際上咱們編程時也是要從這些地方開始訪問數據),全部這些對象,以及被這些對象所指向的對象,都是活的對象。活的對象所指向的對象也是活的對象。GC經過有向圖的進行可達性分析,不可達的對象就被視爲是垃圾對象。
- 因此只要在GC的時刻,讓程序暫停運行,而後從GC Roots開始分析,最後沒有被標記爲活對象的對象就是垃圾了。
*代碼事例解釋什麼是循環引用:對象
如上圖所示,假設咱們有兩個類分別是A和B,A類中有一個字段是B類的類型,B類中有一個字段是A類類型,如今分別new一個A類對象和new一個B類對象,此時引用a指向剛new出來的A類對象,引用b指向剛new出來的B類對象,而後將兩個類中的字段互相引用一下,這樣即便下面進行a = null和b = null,可是A類對象仍然被B類對象中的字段引用着,儘管如今A類和B類獨享都已經訪問不到了,可是引用計數卻都不爲0.blog
三.Java中有哪幾種引用生命週期
- 強引用(StrongReference):強引用就是咱們平時使用的引用,是使用最廣泛的引用。若是一個對象具備強引用,那垃圾回收器毫不會回收它(結合上面,一個對象有強引用,那麼這個對象必定可達,也就是說明這個對象是活的)。當內存空間不足,Java虛擬機寧願拋出OutOfMemoryError錯誤,使程序異常終止,也不會靠隨意回收具備強引用的對象來解決內存不足的問題。(簡記:永不回收)
- 軟引用(SoftReference):若是一個對象只具備軟引用,則內存空間足夠,垃圾回收器就不會回收它;若是內存空間不足了,就會回收這些對象的內存。只要垃圾回收器沒有回收它,該對象就能夠被程序使用。因此,軟引用可用來實現內存敏感的高速緩存。(簡記:內存不足再回收)
- 弱引用(WeakReference):弱引用與軟引用的區別在於:弱引用的對象擁有更短暫的生命週期。在垃圾回收器線程掃描它所管轄的內存區域的過程當中,一旦發現了只具備弱引用的對象,無論當前內存空間足夠與否,都會回收它的內存。不過,因爲垃圾回收器是一個優先級很低的線程,所以不必定會很快發現那些只具備弱引用的對象。(簡記:遇到就回收)
- 虛引用(PhantomReference):「虛引用」顧名思義,就是形同虛設,與其餘幾種引用都不一樣,虛引用並不會決定對象的生命週期。若是一個對象僅持有虛引用,那麼它就和沒有任何引用同樣,在任什麼時候候均可能被垃圾回收器回收。虛引用主要用來跟蹤對象被垃圾回收器回收的活動。虛引用與軟引用和弱引用的一個區別在於:虛引用必須和引用隊列(ReferenceQueue)聯合使用。當垃圾回收器準備回收一個對象時,若是發現它還有虛引用,就會在回收對象的內存以前,把這個虛引用加入到與之關聯的引用隊列中。(簡記:形同虛設)