Java虛擬機器學習 - 垃圾收集器

zhoubangding發表於2017-02-15

轉自:http://blog.csdn.net/java2000_wl/article/details/8030172

HotSpot JVM收集器

              上面有7中收集器,分為兩塊,上面為新生代收集器,下面是老年代收集器。如果兩個收集器之間存在連線,就說明它們可以搭配使用。

Serial(序列GC)收集器

Serial收集器是一個新生代收集器,單執行緒執行,使用複製演算法。它在進行垃圾收集時,必須暫停其他所有的工作執行緒(使用者執行緒)。是Jvm client模式下預設的新生代收集器。對於限定單個CPU的環境來說,Serial收集器由於沒有執行緒互動的開銷,專心做垃圾收集自然可以獲得最高的單執行緒收集效率。

ParNew(並行GC)收集器

ParNew收集器其實就是serial收集器的多執行緒版本,除了使用多條執行緒進行垃圾收集之外,其餘行為與Serial收集器一樣。(所以也是使用複製演算法進行垃圾收集)

Parallel Scavenge(並行回收GC)收集器

Parallel Scavenge收集器也是一個新生代收集器,它也是使用複製演算法的收集器,又是並行多執行緒收集器。parallel Scavenge收集器的特點是它的關注點與其他收集器不同,CMS等收集器的關注點是儘可能地縮短垃圾收集時使用者執行緒的停頓時間,而parallel Scavenge收集器的目標則是達到一個可控制的吞吐量。吞吐量= 程式執行時間/(程式執行時間 + 垃圾收集時間),虛擬機器總共執行了100分鐘。其中垃圾收集花掉1分鐘,那吞吐量就是99%。

----------------------------------------------------   新生代GC/老年代GC分割線  --------------------------------------------------------------

Serial Old(序列GC)收集器

Serial Old是Serial收集器的老年代版本,它同樣使用一個單執行緒執行收集,使用“標記-整理”演算法。主要使用在Client模式下的虛擬機器。

Parallel Old(並行GC)收集器

Parallel Old是Parallel Scavenge收集器的老年代版本,使用多執行緒和“標記-整理”演算法。

CMS(併發GC)收集器

CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時間為目標的收集器。CMS收集器是基於“標記-清除”演算法實現的,整個收集過程大致分為4個步驟:

①.初始標記(CMS initial mark)

②.併發標記(CMS concurrenr mark)

③.重新標記(CMS remark)

④.併發清除(CMS concurrent sweep)

     其中初始標記、重新標記這兩個步驟仍然需要停頓其他使用者執行緒。初始標記僅僅只是標記出GC ROOTS能直接關聯到的物件,速度很快,併發標記階段是進行GC ROOTS 根搜尋演算法階段,會判定物件是否存活。而重新標記階段則是為了修正併發標記期間,因使用者程式繼續執行而導致標記產生變動的那一部分物件的標記記錄,這個階段的停頓時間會被初始標記階段稍長,但比並發標記階段要短。

     由於整個過程中耗時最長的併發標記和併發清除過程中,收集器執行緒都可以與使用者執行緒一起工作,所以整體來說,CMS收集器的記憶體回收過程是與使用者執行緒一起併發執行的。

CMS收集器的優點:併發收集、低停頓,但是CMS還遠遠達不到完美,器主要有三個顯著缺點:

CMS收集器對CPU資源非常敏感。在併發階段,雖然不會導致使用者執行緒停頓,但是會佔用CPU資源而導致引用程式變慢,總吞吐量下降。CMS預設啟動的回收執行緒數是:(CPU數量+3) / 4。

CMS收集器無法處理浮動垃圾,可能出現“Concurrent Mode Failure“,失敗後而導致另一次Full  GC的產生。由於CMS併發清理階段使用者執行緒還在執行,伴隨程式的執行自熱會有新的垃圾不斷產生,這一部分垃圾出現在標記過程之後,CMS無法在本次收集中處理它們,只好留待下一次GC時將其清理掉。這一部分垃圾稱為“浮動垃圾”。也是由於在垃圾收集階段使用者執行緒還需要執行,

即需要預留足夠的記憶體空間給使用者執行緒使用,因此CMS收集器不能像其他收集器那樣等到老年代幾乎完全被填滿了再進行收集,需要預留一部分記憶體空間提供併發收集時的程式運作使用。在預設設定下,CMS收集器在老年代使用了68%的空間時就會被啟用,也可以通過引數-XX:CMSInitiatingOccupancyFraction的值來提供觸發百分比,以降低記憶體回收次數提高效能。要是CMS執行期間預留的記憶體無法滿足程式其他執行緒需要,就會出現“Concurrent Mode Failure”失敗,這時候虛擬機器將啟動後備預案:臨時啟用Serial Old收集器來重新進行老年代的垃圾收集,這樣停頓時間就很長了。所以說引數-XX:CMSInitiatingOccupancyFraction設定的過高將會很容易導致“Concurrent Mode Failure”失敗,效能反而降低。

最後一個缺點,CMS是基於“標記-清除”演算法實現的收集器,使用“標記-清除”演算法收集後,會產生大量碎片。空間碎片太多時,將會給物件分配帶來很多麻煩,比如說大物件,記憶體空間找不到連續的空間來分配不得不提前觸發一次Full  GC。為了解決這個問題,CMS收集器提供了一個-XX:UseCMSCompactAtFullCollection開關引數,用於在Full  GC之後增加一個碎片整理過程,還可通過-XX:CMSFullGCBeforeCompaction引數設定執行多少次不壓縮的Full  GC之後,跟著來一次碎片整理過程。

G1收集器

G1(Garbage First)收集器是JDK1.7提供的一個新收集器,G1收集器基於“標記-整理”演算法實現,也就是說不會產生記憶體碎片。還有一個特點之前的收集器進行收集的範圍都是整個新生代或老年代,而G1將整個Java堆(包括新生代,老年代)。

垃圾收集器引數總結

-XX:+<option> 啟用選項
-XX:-<option> 不啟用選項
-XX:<option>=<number> 
-XX:<option>=<string>

引數 描述

-XX:+UseSerialGC

Jvm執行在Client模式下的預設值,開啟此開關後,使用Serial + Serial Old的收集器組合進行記憶體回收
-XX:+UseParNewGC 開啟此開關後,使用ParNew + Serial Old的收集器進行垃圾回收
-XX:+UseConcMarkSweepGC 使用ParNew + CMS +  Serial Old的收集器組合進行記憶體回收,Serial Old作為CMS出現“Concurrent Mode Failure”失敗後的後備收集器使用。
-XX:+UseParallelGC Jvm執行在Server模式下的預設值,開啟此開關後,使用Parallel Scavenge +  Serial Old的收集器組合進行回收
-XX:+UseParallelOldGC 使用Parallel Scavenge +  Parallel Old的收集器組合進行回收
-XX:SurvivorRatio 新生代中Eden區域與Survivor區域的容量比值,預設為8,代表Eden:Subrvivor = 8:1
-XX:PretenureSizeThreshold 直接晉升到老年代物件的大小,設定這個引數後,大於這個引數的物件將直接在老年代分配
-XX:MaxTenuringThreshold 晉升到老年代的物件年齡,每次Minor GC之後,年齡就加1,當超過這個引數的值時進入老年代
-XX:UseAdaptiveSizePolicy 動態調整java堆中各個區域的大小以及進入老年代的年齡
-XX:+HandlePromotionFailure 是否允許新生代收集擔保,進行一次minor gc後, 另一塊Survivor空間不足時,將直接會在老年代中保留
-XX:ParallelGCThreads 設定並行GC進行記憶體回收的執行緒數
-XX:GCTimeRatio GC時間佔總時間的比列,預設值為99,即允許1%的GC時間,僅在使用Parallel Scavenge 收集器時有效
-XX:MaxGCPauseMillis 設定GC的最大停頓時間,在Parallel Scavenge 收集器下有效
-XX:CMSInitiatingOccupancyFraction 設定CMS收集器在老年代空間被使用多少後出發垃圾收集,預設值為68%,僅在CMS收集器時有效,-XX:CMSInitiatingOccupancyFraction=70
-XX:+UseCMSCompactAtFullCollection
由於CMS收集器會產生碎片,此引數設定在垃圾收集器後是否需要一次記憶體碎片整理過程,僅在CMS收集器時有效
-XX:+CMSFullGCBeforeCompaction
設定CMS收集器在進行若干次垃圾收集後再進行一次記憶體碎片整理過程,通常與UseCMSCompactAtFullCollection引數一起使用
-XX:+UseFastAccessorMethods
原始型別優化
-XX:+DisableExplicitGC
是否關閉手動System.gc
-XX:+CMSParallelRemarkEnabled
降低標記停頓
-XX:LargePageSizeInBytes
記憶體頁的大小不可設定過大,會影響Perm的大小,-XX:LargePageSizeInBytes=128m

Client、Server模式預設GC

  新生代GC方式 老年代和持久GC方式

Client

Serial 序列GC Serial Old 序列GC
Server Parallel Scavenge  並行回收GC Parallel Old 並行GC

Sun/Oracle JDK GC組合方式

  新生代GC方式 老年代和持久GC方式

-XX:+UseSerialGC

Serial 序列GC Serial Old 序列GC
-XX:+UseParallelGC Parallel Scavenge  並行回收GC Serial Old  並行GC
-XX:+UseConcMarkSweepGC ParNew 並行GC CMS 併發GC
當出現“Concurrent Mode Failure”時
採用Serial Old 序列GC
-XX:+UseParNewGC ParNew 並行GC Serial Old 序列GC
-XX:+UseParallelOldGC Parallel Scavenge  並行回收GC Parallel Old 並行GC
-XX:+UseConcMarkSweepGC
-XX:+UseParNewGC
Serial 序列GC CMS 併發GC 
當出現“Concurrent Mode Failure”時
採用Serial Old 序列GC

             本文原文連結:http://blog.csdn.net/java2000_wl/article/details/8030172 轉載請註明出處!


相關文章