Java11新特性 – Epsilon GC和ZGC

  • 2019 年 11 月 1 日
  • 筆記

Java11中新增了兩個GC,Epsilon GC和ZGC。

Epsilon垃圾收集器

A NoOp Garbage Collector
沒有操作的垃圾收集器

JDK上對這個特性的描述是:開發一個處理記憶體分配但不實現任何實際記憶體回收機制的GC, 一旦可用堆記憶體用完,JVM就會退出。
如果有System.gc()調用,實際上什麼也不會發生(這種場景下和-XX:+DisableExplicitGC效果一樣), 因為沒有記憶體回收,這個實現可能會警告用戶嘗試強制GC是徒勞。

用法

-XX:+UnlockExperimentalVMOptions  -XX:+UseEpsilonGC

測試默認GC

我們寫一段程式碼,不斷的產生垃圾:

public class EpsilonTest {      public static void main(String[] args) {          boolean flag = true;          List<Garbage> garbageList = new ArrayList<>();          int count = 0;          while (flag) {              garbageList.add(new Garbage());              if (count ++ == 500) {                  garbageList.clear();              }          }      }  }    class Garbage {      private double d1 = 1;      private double d2 = 2;        /**       * 在GC清除對象時會調用一次       */      @Override      protected void finalize() throws Throwable {          System.out.println(this + " collecting");      }  }

直接運行,使用的默認的垃圾回收器:

java11.Garbage@37c7d031 collecting  java11.Garbage@71a19bf9 collecting  java11.Garbage@3b2df791 collecting  java11.Garbage@61441b29 collecting  java11.Garbage@680b1968 collecting  java11.Garbage@158829c3 collecting  java11.Garbage@414dc59c collecting  java11.Garbage@1103cf collecting  ......

從運行列印的結果可以看出:有對象被回收了,觸發了GC【默認用的是G1】
因為我只限定回收了500個,500個之後的對象會不斷加到記憶體中,記憶體就會不夠用:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space      at java11.EpsilonTest.main(EpsilonTest.java:16)

測試Epsilon GC

如果我使用的是Epsilon GC,會是什麼樣的結果呢?

使用方法

啟動時添加VM參數:

運行結果

運行程式碼,發現控制台沒有任何的輸出,即EpsilonGC不會做任何的回收,並且程式很快就因為堆空間不足而退出。

Terminating due to java.lang.OutOfMemoryError: Java heap space

使用這個選項的原因

提供完全被動的GC實現, 具有有限的分配限制和儘可能低的延遲開銷,但代價是記憶體佔用和記憶體吞吐量.
眾所周知, java實現可廣泛選擇高度可配置的GC實現. 各種可用的收集器最終滿足不同的需求, 即使它們的可配置性使它們的功能相交. 有時更容易維護單獨的實現, 而不是在現有GC實現上堆積另一個配置選項.

主要用途

  • 性能測試(它可以幫助過濾掉GC引起的性能假象)
  • 記憶體壓力測試(例如,知道測試用例 應該分配不超過1GB的記憶體, 我們可以使用-Xmx1g –XX:+UseEpsilonGC, 如果程式有問題, 則程式會崩潰)
  • 非常短的JOB任務(對象這種任務, 接受GC清理堆那都是浪費空間)
  • VM介面測試
  • Last-drop 延遲&吞吐改進

ZGC

ZGC, A Scalable Low-Latency Garbage Collector(Experimental)
ZGC是一款可伸縮、低延遲的GC

概述

ZGC,應該是JDK11最為矚目的特性。但是後面帶了Experimental,說明這還不建議用到生產環境。

  • GC暫停時間不會超過10ms
  • 既能處理幾百兆的小堆, 也能處理幾個T的大堆(OMG)
  • 和G1相比, 應用吞吐能力不會下降超過15%
  • 為未來的GC功能和利用colord指針以及Load barriers優化奠定基礎
  • 初始只支援64位系統

ZGC的設計目標是:支援TB級記憶體容量,暫停時間低(<10ms),對整個程式吞吐量的影響小於15%。 將來還可以擴展實現機制,以支援不少令人興奮的功能,例如多層堆(即熱對象置於DRAM和冷對象置於NVMe快閃記憶體),或壓縮堆。

在使用G1的時候,在回收垃圾的時候,必須要保證應用程式當中所有的執行緒停下來,不在記憶體中製造混亂,然後GC才會開始工作,會造成停頓。這一個過程,有一個專屬名詞來解釋:STW(stop the world)。
ZGC的目標就是縮短STW的時間:ZGC是一個並發,基於region, 壓縮型的垃圾收集器,只有root掃描階段會STW, 因此GC停頓時間不會隨著堆的增長和存活對象的增長而變長。

用法

-XX:+UnlockExperimentalVMOptions  -XX:+UseZGC

ps:ZGC暫時不能在windows系統中使用,不知道最新的版本有沒有支援,我手邊沒有windows機器,未做測試。