java11新特性--Epsilon:A No-Op Garbage Collector

宋兵甲發表於2018-10-03

簡介

Epsilon垃圾回收器控制記憶體分配,但是不執行任何垃圾回收工作。一旦java的堆被耗盡,jvm就直接關閉。

目標

提供一個完全消極的GC實現,分配有限的記憶體分配,最大限度降低消費記憶體佔用量和記憶體吞吐時的延遲時間。一個好的實現是隔離程式碼變化,不影響其他GC,對小限度的改變其他的JVM程式碼。

誤區

它不是為了提供給java語言或jvm一個手動管理記憶體的功能。它不是為了介紹一種新的管理java heap的API。它不是為了適配自己而改變或清除JVM的內部介面。

動機

java實現了一系列的高度可配置化的GC實現。各種不同的垃圾回收器可以面對各種情況。但是有些時候使用一種獨特的實現,而不是將其堆積在其他GC實現上將會是事情變得更加簡單。

下面是no-op GC的幾個使用場景:

  • Performance testing,什麼都不執行的GC非常適合用於差異性分析。no-op GC可以用於過濾掉GC誘發的新能損耗,比如GC執行緒的排程,GC屏障的消耗,GC週期的不合適觸發,記憶體位置變化等。此外有些延遲者不是由於GC引起的,比如scheduling hiccups, compiler transition hiccups,所以去除GC引發的延遲有助於統計這些延遲。
  • Memory pressure testing, 在測試java程式碼時,確定分配記憶體的閾值有助於設定記憶體壓力常量值。這時no-op就很有用,它可以簡單地接受一個分配的記憶體分配上限,當記憶體超限時就失敗。例如:測試需要分配小於1G的記憶體,就使用-Xmx1g引數來配置no-op GC,然後當記憶體耗盡的時候就直接crash。
  • VM interface testing, 以VM開發視角,有一個簡單的GC實現,有助於理解VM-GC的最小介面實現。它也用於證明VM-GC介面的健全性。
  • Extremely short lived jobs, 一個短宣告週期的工作可能會依賴快速退出來釋放資源,這個時候接收GC週期來清理heap其實是在浪費時間,因為heap會在退出時清理。並且GC週期可能會佔用一會時間,因為它依賴heap上的資料量。
  • Last-drop latency improvements, 對那些極端延遲敏感的應用,開發者十分清楚記憶體佔用,或者是幾乎沒有垃圾回收的應用,此時耗時較長的GC週期將會是一件壞事。
  • Last-drop throughput improvements, 即便對那些無需記憶體分配的工作,選擇一個GC意味著選擇了一系列的GC屏障,所有的OpenJDK GC都是分代的,所以他們至少會有一個寫屏障。避免這些屏障可以帶來一點點的吞吐量提升。

描述

Epsilon垃圾回收器和其他OpenJDK的垃圾回收器一樣,使用-XX:+UseEpsilonGC開啟。

Epsilon線性分配單個連續記憶體塊。可複用現存VM程式碼中的TLAB部分的分配功能。非TLAB分配也是同一段程式碼,因為在此方案中,分配TLAB和分配大物件只有一點點的不同。

Epsilon用到的barrier是空的(或者說是無操作的)。因為該GC不執行任何的GC週期,不用關係物件圖,物件標記,物件複製等。引進一種新的barrier-set實現可能是該GC對JVM最大的變化。

當java heap耗盡的時候,因為沒有記憶體回收,沒有記憶體再利用,所以我們會得到系統出錯。下面有幾個選項,這些大多在現有GC中已經出現過了:

  • 丟擲帶有描述資訊的OutOfMemoryError異常
  • 執行heap dump操作(當帶有-XX:+HeapDumpOnOutOfMemoryError時)
  • 失敗掉JVM並且執行可選的外部操作(使用 -XX:OnOutOfMemoryError=…),比如開啟一段除錯程式或者通知外部監控系統

System.gc()將變得無效,因為沒有記憶體回收操作。它的實現可能是告訴使用者嘗試強行GC是無效的。


相關文章