Java 9至12的新功能(第三集)《G1 GC》

《這一回的內容會對於新手比較複雜。儘管很多編程新手都聽過垃圾回收(Garbage Collection或GC)的概念,但通常中級程序員才會比較深入地探索這概念。

雖然GC的背後運作原理是比較複雜,但畢竟它是一個非常重要的概念,它存在是因為在一個程式有很多的Object都是臨時製造的,而很多Object用完了之後就可以被刪除(就好像你硬碟有很多文檔都可以用完之後被刪除),從而騰空RAM記憶體的一些空間。

有很多科技企業都非常注重研究一些方法令一個大型的程式去盡量減少使用RAM,所以我建議新手也可開始學習GC。

(我未來可能會寫帖子講解一下GC的基本概念,但這一回我會跳過GC的基本概念)》

雖然G1 GC已於Java 7推出的時候面世,但到了Java 9才成為JVM預設的GC。

使用G1 GC

想享用G1 GC的話就會在VM options加–XX:+UseG1GC flag

G1 GC的架構

O = Old
S = Survivor
E = Eden
U = Unassigned

G1 GC的架構就是它不會像傳統的CMS GC那樣分為3個heaps,而是分為不同的regions,每個region都可以為2MB到32MB的面積不等,目的就是要減短GC進行的時間。

CMS GC需時長的原因正正是因為它要清理垃圾的時候,它要掃整個heap,將垃圾從Old傳送到去Survivor,再從Survivor傳到Eden,但是G1 GC的速度比較快就在於它可以挑選一些細小的regions掃,不必一次掃整個GC。

Old GC – Concurrent Mark & Sweep (CMS) GC

為什麼擁有很多細小的region可以提升清理垃圾的速度呢?

如果GC想騰空出記憶體的話,它就會挑選一些比較多垃圾的regions去騰空。譬如region A是一個2MB的Eden Space region,它當中有89%都是可丟棄的垃圾,那G1 GC就可以很快地將剩餘11%的live reference傳到鄰近region B的survivor space,而不需像CMS GC那般每次想騰空記憶體的時候都掃整個Eden space(一般的Eden space可以被設為64MB或更大),你每次掃64MB的空間就會花費更長的時間(相比起掃G1 GC的2MB region)。

當G1 GC一個region擁有100%垃圾的時候

但是G1 GC最理想的情況就是當一個region全部都是100%垃圾,G1 GC就可以直接把它垃圾抗直接變為Unassigned,這就會非常省時。當一個region變為Unassigned的時候,那個空間就是被騰空出來,令將來的live references倒進去。

相反,CMS GC就不可以這樣挑選一個擁有100%垃圾的region出來,除非你整個Young space都滿了。但Young space滿了就代表你JVM不夠記憶體去容納更多的live references,在執行大程式的時候,這是十分危險的。若JVM每次Young space 100%滿了才開始清理的話就會影響你Java程式本身產生live references的速度,足以令你的Java程式運行變慢。

Leave a Reply

Your email address will not be published. Required fields are marked *