JVM GC原理深度解析及性能調優實戰(三)

如何確定垃圾

引用計數法

在Java中,引用和對象是有關聯的。如果要操作對象則必須用引用進行。因此,很顯然一個簡單的辦法是通過引用計數來判斷一個對象是否可以回收。簡單說,即一個對象如果沒有任何與之關聯的引用,即他們的引用計數都不為0,則說明對象不太可能再被用到,那麼這個對象就是可回收對象。

可達性分析

為了解決引用計數法的循環引用問題,Java使用了可達性分析的方法。通過一系列的“GC roots”對象作為起點搜索。如果在“GC roots”和一個對象之間沒有可達路徑,則稱該對象是不可達的。

要注意的是,不可達對象不等價於可回收對象,不可達對象變為可回收對象至少要經過兩次標記過程。兩次標記後仍然是可回收對象,則將面臨回收。

回收算法

標記清楚算法

最基礎的垃圾回收算法,分為兩個階段,標註和清除。標記階段標記出所有需要回收的對象,清除階段回收被標記的對象所佔用的空間。

JVM GC原理深度解析及性能調優實戰(三)

如圖該算法最大的問題是內存碎片化嚴重,後續可能發生大對象不能找到可利用空間的問題。

複製算法

為了解決Mark-Sweep算法內存碎片化的缺陷而被提出的算法。按內存容量將內存劃分為等大小的兩塊。每次只使用其中一塊,當這一塊內存滿後將尚存活的對象複製到另一塊上去,把已使用的內存清掉。

JVM GC原理深度解析及性能調優實戰(三)

這種算法雖然實現簡單,內存效率高,不易產生碎片,但是最大的問題是可用內存被壓縮到了原本的一半。且存活對象增多的話,Copying算法的效率會大大降低。

標記整理算法

結合了以上兩個算法,為了避免缺陷而提出。標記階段和Mark-Sweep算法相同,標記後不是清理對象,而是將存活對象移向內存的一端。然後清除端邊界外的對象。如圖:

JVM GC原理深度解析及性能調優實戰(三)

分代收集算法

分代收集法是目前大部分JVM所採用的方法,其核心思想是根據對象存活的不同生命週期將內存劃分為不同的域,一般情況下將GC堆劃分為老生代(Tenured/Old Generation)和新生代(Young Generation)。老生代的特點是每次垃圾回收時只有少量對象需要被回收,新生代的特點是每次垃圾回收時都有大量垃圾需要被回收,因此可以根據不同區域選擇不同的算法。

1.新生代採用複製算法

目前大部分JVM的GC對於新生代都採取Copying算法,因為新生代中每次垃圾回收都要回收大部分對象,即要複製的操作比較少,但通常並不是按照1:1來劃分新生代。一般將新生代劃分為一塊較大的Eden空間和兩個較小的Survivor空間(From Space, To Space),每次使用Eden空間和其中的一塊Survivor空間,當進行回收時,將該兩塊空間中還存活的對象複製到另一塊Survivor空間中。

2.老年代採用標記整理算法

而老年代因為每次只回收少量對象,因而採用Mark-Compact算法。

1. JAVA虛擬機提到過的處於方法區的永生代(Permanet Generation),它用來存儲class類,常量,方法描述等。對永生代的回收主要包括廢棄常量和無用的類。

2. 對象的內存分配主要在新生代的Eden Space和Survivor Space的From Space(Survivor目前存放對象的那一塊),少數情況會直接分配到老生代。

3. 當新生代的Eden Space和From Space空間不足時就會發生一次GC,進行GC後,Eden Space和From Space區的存活對象會被挪到To Space,然後將Eden Space和From Space進行清理。

4. 如果To Space無法足夠存儲某個對象,則將這個對象存儲到老生代。

5. 在進行GC後,使用的便是Eden Space和To Space了,如此反覆循環。

6. 當對象在Survivor區躲過一次GC後,其年齡就會+1。默認情況下年齡到達15的對象會被移到老生代中。

java四種引用不同的回收規則

強引用:在Java中最常見的就是強引用,把一個對象賦給一個引用變量,這個引用變量就是一個強引用。當一個對象被強引用變量引用時,它處於可達狀態,它是不可能被垃圾回收機制回收的,即使該對象以後永遠都不會被用到JVM也不會回收。因此強引用是造成Java內存洩漏的主要原因之一。

軟引用:軟引用需要用SoftReference類來實現,對於只有軟引用的對象來說,當系統內存足夠時它不會被回收,當系統內存空間不足時它會被回收。軟引用通常用在對內存敏感的程序中。

弱引用:弱引用需要用WeakReference類來實現,它比軟引用的生存期更短,對於只有弱引用的對象來說,只要垃圾回收機制一運行,不管JVM的內存空間是否足夠,總會回收該對象佔用的內存。

虛引用:虛引用需要PhantomReference類來實現,它不能單獨使用,必須和引用隊列聯合使用。虛引用的主要作用是跟蹤對象被垃圾回收的狀態。

下一篇:詳解幾種常用垃圾回收器


分享到:


相關文章: