實戰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 進行回收。
個人微信公眾號: