1. 程式人生 > >JVM之GC收集器

JVM之GC收集器

        JVM中GC垃圾回收機制與垃圾回收演算法一文中已經介紹了垃圾回收機制以及對應的一些回收演算法,本文主要更深入瞭解JVM中的GC機制以及不同GC收集器的工作功用以及優缺點。

         首先,GC的主要區域是堆,而堆主要劃分為新生代和老生代。其中新生代主要劃分為eden、survivor0、survivor1三個區域,且記憶體比例為8:1:1.

                       

1.新生代可用GC

a.序列GC(Serial GC):新生代分配記憶體採用的為空閒指標的方式。基於Copying演算法,需要從根集合掃描出存活的物件。根集合物件:當前執行執行緒的棧上引用的物件、常量及靜態變數、傳到本地方法中,還沒有被本地方法釋放的物件引用。由於是序列工作,所以進行垃圾回收時,必須暫停其它所有的工作執行緒,這會導致GC時間比較長。

注:JDK採用了remember set解決舊生代中的物件引用了新生代的物件的問題。JDK在進行物件賦值時,如果賦值的為一個物件引用,則產生write barrier,然後檢查需要賦值的物件是否在舊生代及賦值的物件是否引用新生代,如果滿足,則在remenber set做個標記,JDK採用了Card Table來實現remeber set。

b.並行回收GC(Parallel Scavenge):需要配置SurvivorRatio來分配Eden、s0、s1的大小。同時會動態調整調整三者的大小。採用Copying演算法,但在掃描和複製的過程中採用多執行緒方式。適合於多CPU,對暫停時間要求較短的應用。是server級別預設回收方式。執行緒數計算方法:CPU核數小於等於8,執行緒數即核數;核數大於8,執行緒數=3+(核數*5)/8.或者用-XX:ParallelGCThreads來指定。

c.並行GC(ParNew):需與舊生代CMS GC配合使用。增加了CPU並行處理,演算法採用的與序列GC相同的演算法。

2.舊生代可用GC

a.序列:基於標記清除和標記整理相結合實現的。對於執行在client模式下的虛擬機器是一個很好的選擇。

b.並行:1)首先將代空間劃分為並行執行緒個數的區域,然後根據集合物件及併發執行緒數進行劃分(三色著色);2)從左往右進行掃描,尋找第一個值得壓縮的存活物件。

c.併發(CMS):free list記錄舊生代哪些部分是空閒的。以獲取最短回收停頓時間為目標的收集器。重視服務的響應速度,希望系統停頓時間最短,給使用者帶來較好的體驗。

1).初始標記 2)併發標記 3)重新標記  4)併發清除

初始標記僅是標記一下GC Roots能直接關聯到的物件,速度很快;併發標記階段就是進行GC Roots Tracing的過程;而重新標記階段則是為了修正併發標記期間因使用者程式繼續運作而導致產生變動的那一部分物件的標記記錄;耗時較長時併發標記和併發清除,但可以與使用者執行緒一起工作。

CMS缺點:

1)CMS收集器對CPU資源非常敏感,總吞吐量降低

2)CMS收集器無法處理浮動垃圾,可能出現concurrent mode failure失效而導致一次full gc產生

3)標記清除導致有大量碎片。

d.G1收集器:面向服務端應用。有四個明顯特點:並行與併發;分代收集;空間整合;可預測的停頓。從整體上來看是基於標記整理,從區域性來看是基於複製演算法。

該類收集器特點是將Java堆劃分為多個大小相等的獨立區域,新生代和老生代不再是物理隔離,而是一部分region的集合。

3.Full GC觸發條件

a.舊生代空間不足

b.CMS GC出現promotion failed和concurent mode failure

c.統計得到的Minor GC晉升到舊生代的平均大小大於舊生代的剩餘空間。