12.06.2014

Garbage Collector的種類

前面(什麼是Garbage Collection)提到身為開發者,Java會自動回收記憶體,讓開發者可以專注在業務邏輯的處理,但在回收的過程中,會造成系統無法回應(取決於Major/Minor GC);因此Java提供了許多不同的Garbage Collector,讓我們可以依據系統的效能需求,選擇最適合的Garbage Collector。
如下圖所示,有七種Garbage Collector,分為上下二個區塊,上面為Young generation,下面為Old/Tenured generation,若二個Garbage Collector之間存在連線,代表可以搭配使用。

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

Serial Collector(-XX:+UseSerialGC)

屬於單一執行緒的copy collector,運作原理是將存活的物件從"from" space (ex.survivor 1)搬至"to" space(ex.survivor 2),並回收"from" space,他主要是設計給heap size需求很小的應用程式使用,由於屬於"Stop-the-world" (當他在執行時,其他任務都必需暫停) collector,所以並不適用於對response time要求高的系統,但相對地也因為單執行緒,讓他可以有最高的GC效率,較為適合用於不要求即時性(ex background job server)的系統。


ParNew Collector(-XX:+UseParNewGC)

Parallel copy collector其實就是multi-thread版的Serial Collector,其餘行為都跟Serial collector相同,效率則因為multi-thread較Serial Collector好。


Parallel Scavenge Collector(-XX:+UseParallelGC)

運作方式跟Parallel copy collector相同,但演算法有針對超過10GB heaps的multi-CPU環境做過最佳化。他的目標是盡可能地取得最大throughput[註1]同時降低GC造成的暫停。若你使用這個collector,則在old generation你可以使用原使的mark-sweep collector(Serial Old)。


CMS(-XX:+UseConcMarkSweepGC)

CMS不同於其他garbage collector,他不會進行heap space compaction(因為compaction的過程很耗時且會造成系統停頓),使他適用於高互動式的系統;但相對地,他也較容易造成記憶體碎片化(fragmentation);雖然CMS不會進行Full GC,但當出現promotion failed/concurrent mode failure時,此時會使用Mark Compact garbage collector (Serial Old GC)進行Full GC,CMS運作分為下面幾個階段:
Initial mark - 這個階段會找出application有直接(root)reference reference的活物件, stop-the-world 。
Concurrent mark – 這個階段會針對上階段結果,追蹤整個object graph,並標記活著的物件,整個過程會和application同時運行。
Concurrent pre clean – 這個階段是針對上一階段標記為活著的物件再做檢查,目的是為了減少Remark造成stop-the-world的時間,整個過程會和application同時運行。
Remark - 因為在進行mark階段,application是持續在運行,新的物件並不會被標記,此時application再度停止運行,並針對在Concurrent mark階段有變動的物件進行最終標記 , stop-the-world 。

Serial Old(-XX:+UseSerialGC)

Serial Old (Mark Sweep Compact:MSC) - 屬於stop-the-world collector,運作原理是先找出活著的物件做標記,之後清除未用的物件,最後再進行compaction。


Parallel Old(-XX:+UseParallelOldGC)

Parallel Scavenge的Old generation版本。


G1(-XX:+UseG1GC)

G1GC在Java7時加入,他的目標是在不犧牲throughput的狀況下,達成low latency。傳統GC會將heap分為3個區塊:young generation,old generation以及permanent generation,每個區塊都設定了固定大小;G1GC則是將heap分割成一塊塊相同大小的region,每個resion大約是1MB~32MB的連續記憶體空間,再將一個個region組成region sets,同一個region set扮演相同的角色(eden, survivor或old),因為region set沒固定大小,若服務中大部份的物件存活期都很短,則young generation會佔大部份;反之則tenured generation佔大部份,因此使用G1GC時,調整新世代大小的參數就不重要了,這種方式提供了記憶體使用上的更大彈性。

G1GC的GC過程跟CMS很類似,都是分階段標記後再回收,差別在於回收的方式。G1GC將記憶體分割為許多region,GC時並不會一次對所有region都進行回收,而是會依據允許的時間(預設為200ms),能回收多少region就做多少,藉此精準地控制停頓的時間,GC會先回收垃圾最多的region,以釋放最多空間,這也就是為什麼他叫Garbage First的原因。回收的過程採用驅離(evacuation)的方式,從一個或多個region將活著的物件搬至另一個region,藉此同時進行記憶體回收以及compaction,避免了heap破碎化的問題。



[註1]Throughput的定義是扣除GC花費的時間,系統可以使用的時間比;也就是[系統可用時間]/[總系統執行時間]。

No comments: