【JVM進階之路】七:垃圾收集器盤點

在前面,咱們已經瞭解了JVM的分代收集,知道JVM垃圾收集在新生代主要採用標記-複製算法,在老年代主要採用標記-清除標記-整理算法。接下來,咱們看一看JDK默認虛擬機HotSpot的一些垃圾收集器的實現。html

一、常見垃圾回收器

首先來看一下JDK 11以前所有可用的垃圾收集器。java

HotSpot虛擬機

圖中列出了七種垃圾收集器,連線表示能夠配合使用,所在區域表示它是屬於新生代收集器或是老年代收集器。算法

這裏還標出了垃圾收集器採用的收集算法,G1收集器比較特殊,總體採用標記-整理算法,局部採用標記-複製算法,後面再細講。多線程

1.一、Serial收集器

Serial收集器是最基礎、歷史最悠久的收集器。併發

如同它的名字(串行),它是一個單線程工做的收集器,使用一個處理器或一條收集線程去完成垃圾收集工做。而且進行垃圾收集時,必須暫停其餘全部工做線程,直到垃圾收集結束——這就是所謂的「Stop The World」。jvm

Serial/Serial Old收集器的運行過程如圖:高併發

Serial/Serial Old收集器運行示意圖

1.二、ParNew收集器

ParNew收集器實質上是Serial收集器的多線程並行版本,使用多條線程進行垃圾收集。佈局

ParNew收集器的工做過程如圖所示:性能

ParNew/Serial Old收集器運行示意圖

這裏值得一提的是Par是Parallel(並行)的縮寫,但須要注意的是,這個並行(Parallel)僅僅是描述同一時間多條GC線程協同工做,而不是GC線程和用戶線程同時運行。ParNew垃圾收集也是須要Stop The World的。線程

1.三、Parallel Scavenge收集器

Parallel Scavenge收集器是一款新生代收集器,基於標記-複製算法實現,也可以並行收集。和ParNew有些相似,但Parallel Scavenge主要關注的是垃圾收集的吞吐量。

所謂吞吐量指的是運行用戶代碼的時間與處理器總消耗時間的比值。這個比例越高,證實垃圾收集佔整個程序運行的比例越小。

吞吐量

Parallel Scavenge收集器提供了兩個參數用於精確控制吞吐量:

  • -XX:MaxGCPauseMillis,最大垃圾回收停頓時間。這個參數的原理是空間換時間,收集器會控制新生代的區域大小,從而儘量保證回收少於這個最大停頓時間。簡單的說就是回收的區域越小,那麼耗費的時間也越小。
    因此這個參數並非設置得越小越好。設過小的話,新生代空間會過小,從而更頻繁的觸發GC。

  • -XX:GCTimeRatio,垃圾收集時間與總時間佔比。這個是吞吐量的倒數,原理和MaxGCPauseMillis相同。

因爲與吞吐量關係密切,Parallel Scavenge收集器也常常被稱做「吞吐量優先收集器」。

1.四、Serial Old收集器

Serial Old是Serial收集器的老年代版本,它一樣是一個單線程收集器,使用標記-整理算法。

Serial Old收集器的工做過程如圖:

Serial/Serial Old收集器運行示意圖

1.五、Parallel Old收集器

Parallel Old是Parallel Scavenge收集器的老年代版本,支持多線程併發收集,基於標記-整理算法實現。

Parallel Scavenge/Parallel Old收集器運行示意圖

1.六、CMS收集器

CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時間爲目標的收集器,一樣是老年代的收集齊,採用標記-清除算法。

CMS收集齊的垃圾收集分爲四步:

  • 初始標記(CMS initial mark):單線程運行,須要Stop The World,標記GC Roots能直達的對象。
  • 併發標記((CMS concurrent mark):無停頓,和用戶線程同時運行,從GC Roots直達對象開始遍歷整個對象圖。
  • 從新標記(CMS remark):多線程運行,須要Stop The World,標記併發標記階段產生對象。
  • 併發清除(CMS concurrent sweep):無停頓,和用戶線程同時運行,清理掉標記階段標記的死亡的對象。

涉及到了屢次標記的過程,這裏插入一點三色抽象的知識。三色抽象用來描述對象在垃圾收集過程當中的狀態。

一般白色表明對象未被掃描到,灰色表示對象被掃描到但未被處理,黑色表示對象及其後代已被處理。在CMS的標記和清除過程當中就用到了這種抽象,詳細的能夠查看參考【5】。

Concurrent Mark Sweep收集器運行示意圖以下:

Concurrent Mark Sweep收集器運行示意圖

優勢:CMS最主要的優勢在名字上已經體現出來——併發收集、低停頓。

缺點:CMS一樣有三個明顯的缺點。

  • Mark Sweep算法會致使內存碎片比較多

  • CMS的併發能力比較依賴於CPU資源,併發回收時垃圾收集線程可能會搶佔用戶線程的資源,致使用戶程序性能降低。

  • 併發清除階段,用戶線程依然在運行,會產生所謂的理「浮動垃圾」(Floating Garbage),本次垃圾收集沒法處理浮動垃圾,必須到下一次垃圾收集才能處理。若是浮動垃圾太多,會觸發新的垃圾回收,致使性能下降。

1.七、Garbage First收集器

Garbage First(簡稱G1)收集器是垃圾收集器的一個顛覆性的產物,它開創了局部收集的設計思路和基於Region的內存佈局形式。

雖然G1也還是遵循分代收集理論設計的,但其堆內存的佈局與其餘收集器有很是明顯的差別。之前的收集器分代是劃分新生代、老年代、持久代等。

垃圾分代區域

G1把連續的Java堆劃分爲多個大小相等的獨立區域(Region),每個Region均可以根據須要,扮演新生代的Eden空間、Survivor空間,或者老年代空間。收集器可以對扮演不一樣角色的Region採用不一樣的策略去處理。

G1 Heap Regions

這樣就避免了收集整個堆,而是按照若干個Region集進行收集,同時維護一個優先級列表,跟蹤各個Region回收的「價值,優先收集價值高的Region。

G1收集器的運行過程大體可劃分爲如下四個步驟:

  • 初始標記(initial mark),標記了從GC Root開始直接關聯可達的對象。STW(Stop the World)執行。

  • 併發標記(concurrent marking),和用戶線程併發執行,從GC Root開始對堆中對象進行可達性分析,遞歸掃描整個堆裏的對象圖,找出要回收的對象、

  • 最終標記(Remark),STW,標記再併發標記過程當中產生的垃圾。

  • 篩選回收(Live Data Counting And Evacuation),制定回收計劃,選擇多個Region 構成回收集,把回收集中Region的存活對象複製到空的Region中,再清理掉整個舊 Region的所有空間。須要STW。

G1收集器運行示意圖

相比CMS,G1的優勢有不少,能夠指定最大停頓時間、分Region的內存佈局、按收益動態肯定回收集。

只從內存的角度來看,與CMS的「標記-清除」算法不一樣,G1從總體來看是基於「標記-整理」算法實現的收集器,但從局部(兩個Region 之間)上看又是基於「標記-複製」算法實現,不管如何,這兩種算法都意味着G1運做期間不會產生內存空間碎片,垃圾收集完成以後能提供規整的可用內存。

二、前沿垃圾回收器

2.一、ZGC收集器

在JDK 11當中,加入了實驗性質的ZGC。它的回收耗時平均不到2毫秒。它是一款低停頓高併發的收集器。

與CMS中的ParNew和G1相似,ZGC也採用標記-複製算法,不過ZGC對該算法作了重大改進:ZGC在標記、轉移和重定位階段幾乎都是併發的,這是ZGC實現停頓時間小於10ms目標的最關鍵緣由。

ZGC垃圾回收週期

ZGC雖然在JDK 11還處於實驗階段,但因爲算法與思想是一個很是大的提高,將來前景相信仍是很廣闊的。

三、垃圾收集器選擇

3.一、收集器選擇權衡

垃圾收集器的選擇須要權衡的點仍是比較多的——例如運行應用的基礎設施如何?使用JDK的發行商是什麼?等等……

這裏簡單地列一下上面提到的一些收集器的適用場景:

  • Serial :若是應用程序有一個很小的內存空間(大約100 MB)亦或它在沒有停頓時間要求的單線程處理器上運行。
  • Parallel:若是優先考慮應用程序的峯值性能,而且沒有時間要求要求,或者能夠接受1秒或更長的停頓時間。
  • CMS/G1:若是響應時間比吞吐量優先級高,亦或垃圾收集暫停必須保持在大約1秒之內。
  • ZGC:若是響應時間是高優先級的,亦或堆空間比較大。

3.一、設置垃圾收集器

設置垃圾收集器(組合)的參數以下:

新生代 老年代 JVM 參數
Incremental Incremental -Xincgc
Serial Serial -XX:+UseSerialGC
Parallel Scavenge Serial -XX:+UseParallelGC -XX:-UseParallelOldGC
Parallel New Serial N/A
Serial Parallel Old N/A
Parallel Scavenge Parallel Old -XX:+UseParallelGC -XX:+UseParallelOldGC
Parallel New Parallel Old N/A
Serial CMS -XX:-UseParNewGC -XX:+UseConcMarkSweepGC
Parallel Scavenge CMS N/A
Parallel New CMS -XX:+UseParNewGC -XX:+UseConcMarkSweepGC
G1 -XX:+UseG1GC

參考:

【1】:周志朋編著《深刻理解Java虛擬機:JVM高級特性與最佳實踐》

【2】:《垃圾回收算法手冊 自動內存管理的藝術》

【3】:Garbage Collection in Java – What is GC and How it Works in the JVM

【4】:Java Hotspot G1 GC的一些關鍵技術

【5】:GC Algorithms: Implementations

【6】:新一代垃圾回收器ZGC的探索與實踐

相關文章
相關標籤/搜索