實戰JAVA虛擬機:G1

G1(Garbage-First)回收器是在JDK1.7中正式使用的全新垃圾回收器,G1擁有獨特的垃圾回收策略,從分代上看,G1依然屬於分代垃圾回收器,它會區分年代和老年代,依然有eden和survivor區,但從堆的結構上看,它並不要求整個eden區、年清代或者老年代都連續。它使用了全新的分區算法。其特點如下:

  • 並行性:G1在回收期間,可以由多個GC線程同時工作,有效利用多核計算能力。

  • 併發性:G1擁有與應用程序交替執行的能力,因此一般來說,不會在整個回收期間完全阻塞應用程序。

  • 分代GC:與之前回收器不同,其他回收器,它們要麼工作在年輕代要麼工作在老年代。G1可以同時兼顧年輕代與老年代。

  • 空間整理:G1在回收過程中,會進行適當的對象移動,不像CMS,只是簡單的標記清除,在若干次GC後CMS必須進行一次碎片整理,G1在每次回收時都會有效的複製對象,減少空間碎片。

  • 可預見性:由於分區的原因,G1可以只選取部分區域進行內存回收,這樣縮小了回收範圍,因此對於全局停頓也能得到更好的控制。

一、G1的內存劃分和主要收集過程

G1收集回收器將堆進行分區,劃分爲一個個的區域,每次收集的時候,只收集其中幾個區域,以此來控制垃圾回收產生一次停頓時間。
G1的收集過程可能有4個階段:

  • 新生代GC
  • 併發標記週期
  • 混合收集
  • (如果需要)進行Full GC。

二、G1的新生代GC

新生代GC的主要工作是回收eden區和survivor區。一旦eden區被佔滿,新生代GC就會啓動。新生代GC收集前後的堆數據如圖5.6所示,其中E表示eden區,S表示survivor區,O表示老年代。可以看到,新生代GC只處理eden和survivor區,回收後,所有的eden區都應該被清空,而survivor區會被收集一部分數據,但是應該至少仍然存在一個survivor區,類比其他的新生代收集器,這一點似乎並沒有太大變化。另一個重要的變化是老年代的區域增多,因爲部分survivor區或者eden區的對象可能會晉升到老年代。
在這裏插入圖片描述

三、G1併發標記週期

G1的併發階段和CMS有些類似,它們都是爲了降低一次停頓時間,而將可以和應用程序併發執行的部分單獨提取出來執行。

併發標記週期針對老年代

併發標記週期可分爲以下幾步:

  • 初始標記:標記從根節點直接可達的對象。這個階段會伴隨一次新生代GC,它是會產生全局停頓的,應用程序在這個階段必須停止執行。

  • 根區域掃描:由於初始標記必然會伴隨一次新生代GC,所以在初始化標記後,eden被清空,並且存活對象被移到survivor區。在這個階段,將掃描由survivor區直接可達的老年代區域,並標記這些直接可達的對象。 這個過程是可以和應用程序併發執行的。但是根區域掃描不能和新生代GC同時發生(因爲根區域掃描依賴survivor區的對象,而新生代GC會修改這個區域),故如果恰巧此時需要新生代GC,GC就需要等待根區域掃描結束後才能進行,如果發生這種情況,這次新生代GC的時間就會延長。

  • 併發標記:和CMS類似,併發標記將會掃描並查找整個堆的存活對象,並做好標記。這是一個併發過程,並且這個過程可以被一次新生代GC打斷。

  • 重新標記:和CMS一樣,重新標記也是會使應用程序停頓,由於在併發標記過程中,應用程序依然運行,因此標記結果可能需要修正,所以在此階段對上一次標記進行補充。在G1中,這個過程使用SATB(Snapshot-At-The-Begining)算法完成,即G1會在標記之初爲存活對象創建一個快照,這個快照有助於加速重新標記的速度。

  • 獨佔清理:顧名思義,這個階段會引起停頓。它將計算各個區域的存活對象和GC回收比例並進行排序,識別可供混合回收的區域。在這個階段,還會更新記憶集。該階段給出了需要被混合回收的區域並進行了標記,在混合回收階段,需要這些信息。

  • 併發清理階段:識別並清理完全空閒的區域。它是併發的清理,不會引起停頓。

四、混合回收

在併發標記週期中,雖有部分對象被回收,但是回收的比例是非常低的。但是在併發標記週期後,G1已經明確知道哪些區域含有比較多的垃圾對象,在混合回收階段,就可以專門針對這些區域進行回收。當然G1會優先回收垃圾比例較高的區域(回收這些區域的性價比高),這正是G1名字的由來(Garbage First Garbage Collector:譯爲垃圾優先的垃圾回收器),這裏的垃圾優先(Garbage First)指的是回收時優先選取垃圾比例最高的區域。

這個階段叫做混合回收,是因爲在這個階段,即會執行正常的年輕帶GC,又會選取一些被標記的老年代區域進行回收,同時處理了新生代和老年代。

混合回收會被執行多次,直到回收了足夠多的內存空間,然後,它會觸發一次新生代GC。新生代GC後,又可能會發生一次併發標記週期的處理,最後又會引起混合回收,因此整個過程可能是如下圖:
在這裏插入圖片描述

五、必要時的Full GC

和CMS類似,併發收集讓應用程序和GC線程交替工作,因此在特別繁忙的情況下無可避免的會發生回收過程中內存不足的情況,當遇到這種情況,G1會轉入一個Full GC 進行回收。

本文整理自:《實戰JAVA虛擬機 JVM故障診斷與性能優化》

個人微信公衆號:
這裏寫圖片描述

作者:jiankunking 出處:http://blog.csdn.net/jiankunking

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章