【JVM】如何選擇垃圾回收器?

明確垃圾回收器組合

-XX:+UseSerialGC 年輕代和老年代都用串行收集器
-XX:+UseParNewGC 年輕代使用ParNew,老年代使用 Serial Old
-XX:+UseParallelGC 年輕代使用Paraller Scavenge,老年代使用Serial Old
-XX:+UseParallelOldGC 新生代Paraller Scavenge,老年代使用Paraller Old
-XX:+UseConcMarkSweepGC,表示年輕代使用ParNew,老年代的用CMS + Serial Old
-XX:+UseG1GC 使用G1垃圾回收器
-XX:+UseZGC 使用ZGC垃圾回收器java

垃圾收集器跟內存大小的大體關係(不精確,須要根據實際環境測試)

  1. Serial:幾十兆
  2. PS:上百兆 ~ 4G
  3. CMS:4G ~ 10G
  4. G1:10G~上百G
  5. ZGC: 4T - 16T(JDK13)

常見的垃圾回收器

  1. JDK誕生 Serial追隨 提升效率,誕生了PS,爲了配合CMS,誕生了PN,CMS是1.4版本後期引入,CMS是里程碑式的GC,它開啓了併發回收的過程,可是CMS毛病較多,所以目前任何一個JDK版本默認是CMS 併發垃圾回收是由於沒法忍受STW
  2. Serial 年輕代 串行回收
  3. PS 年輕代 並行回收
  4. ParNew 年輕代 配合CMS的並行回收
  5. SerialOld
  6. ParallelOld
  7. ConcurrentMarkSweep 老年代 併發的, 垃圾回收和應用程序同時運行,下降STW的時間(200ms) CMS問題比較多,因此如今沒有一個版本默認是CMS,只能手工指定 CMS既然是MarkSweep,就必定會有碎片化的問題,碎片到達必定程度,CMS的老年代分配對象分配不下的時候,使用SerialOld 進行老年代回收 想象一下:PS + PO -> 加內存 換垃圾回收器 -> PN + CMS + SerialOld(幾個小時 - 幾天的STW) 幾十個G的內存,單線程回收 -> G1 + FGC 幾十個G -> 上T內存的服務器 ZGC 算法:三色標記 + Incremental Update
  8. G1(10ms) 算法:三色標記 + SATB
  9. ZGC (1ms) PK C++ 算法:ColoredPointers + LoadBarrier
  10. Shenandoah 算法:ColoredPointers + WriteBarrier
  11. Eplison

常見垃圾回收器組合參數設定:(1.8)

  • -XX:+UseSerialGC = Serial New (DefNew) + Serial Old
    小型程序。默認狀況下不會是這種選項,HotSpot會根據計算及配置和JDK版本自動選擇收集器算法

  • -XX:+UseParNewGC = ParNew + SerialOld這個組合已經不多用(在某些版本中已經廢棄)服務器

  • -XX:+UseConc(urrent)MarkSweepGC = ParNew + CMS + Serial Old架構

  • -XX:+UseParallelGC = Parallel Scavenge + Parallel Old (1.8默認) 【PS + SerialOld】併發

  • -XX:+UseParallelOldGC = Parallel Scavenge + Parallel Old測試

  • -XX:+UseG1GC = G1操作系統

  • 默認GC的查看方法
    1.java -XX:+PrintCommandLineFlags -version
    2.經過GC的日誌來分辨線程

  • Linux下1.8版本默認的垃圾回收器究竟是什麼?日誌

    • 1.8.0_181 默認(看不出來)Copy MarkCompact
    • 1.8.0_222 默認 PS + PO

面對如此衆多的垃圾回收器,咱們應該如何選擇一款適合本身應用的收集器呢?這個問題的答案主要受如下三個因素影響:對象

應用程序的主要關注點是什麼?

  1. 數據分析、科學計算類的任務,目標是能儘快算出結果,那吞吐量就是主要關注點;
  2. SLA 應用,那停頓時間直接影響服務質量,嚴重的甚至會致使事務超時,這樣延遲就是主要關注點;
  3. 客戶端應用或者嵌入式應用,那垃圾收集的內存佔用則是不可忽視的。

運行應用的基礎設施如何?

譬如硬件規格,要涉及的系統架構是 x86-32/6四、SPARC 仍是ARM/Aarch64;處理器的數量多少,分配內存的大小;選擇的操做系統是 Linux、Solaris 仍是 Windows等。

使用 JDK 的發行商是什麼?

版本號是多少?是 ZingJDK/Zulu、OracleJDK、Open-JDK、OpenJ9 抑或是其餘公司的發行版?該 JDK 對應了《Java 虛擬機規範》的哪一個版本?

舉例說明

通常來講,收集器的選擇就從以上這幾點出發來考慮。
舉個例子,假設某個直接面向用戶提供服務的 B/S 系統準備選擇垃圾收集器,通常來講延遲時間是這類應用的主要關注點,那麼:

  1. 若是你有充足的預算但沒有太多調優經驗,那麼一套帶商業技術支持的專有硬件或者軟件解決方案是不錯的選擇,Azul 公司之前主推的 Vega 系統和如今主推的 Zing VM 是這方面的表明,這樣你就可使用傳說中的 C4 收集器了。

  2. 若是你雖然沒有足夠預算去使用商業解決方案,但可以掌控軟硬件型號,使用較新的版本,同時又特別注重延遲,那 ZGC 很值得嘗試。

  3. 若是你對還處於實驗狀態的收集器的穩定性有所顧慮,或者應用必須運行在 Win-dows 操做系統下,那 ZGC 就無緣了,試試 Shenandoah 吧

  4. 若是你接手的是遺留系統,軟硬件基礎設施和 JDK 版本都比較落後,那就根據內存規模衡量一下,對於大概 10G 如下的堆內存,CMS 通常能處理得比較好,而對於更大的堆內存,可重點考察一下 G1。(這個通常現階段使用較多)

    固然,以上都是僅從理論出發的分析,實戰中切不可紙上談兵,根據系統實際狀況去測試纔是選擇收集器的最終依據。

相關文章
相關標籤/搜索