没有垃圾回收的JVM
JVM社區不斷增加新的GC,最近又添加了一個新的GC,它稱為Epsilon ,是非常特殊的一個。 Epsilon僅分配內存,但不會回收任何內存。
看起來好像不執行任何垃圾回收的GC用途是什么。 這種類型的垃圾收集器有特殊用途,我們將對其進行研究。
可以在哪里使用此靈巧的GC?
性能測試
如果您正在開發對延遲要求嚴格且內存預算有限的解決方案,那么此GC可用于測試程序限制。
內存壓力測試
想知道您的應用程序提取瞬態內存需求。 如果您要構建一些純粹的內存中解決方案,我會發現這很有用。
基準標記算法。
很多時候,我們希望基于對BIG(O)概念的理解來測試新的酷算法的真實性能,但是垃圾收集器會在測試過程中增加噪音。
低垃圾
很多時候,我們在算法上進行了一些優化以減少產生的垃圾,而像epsilon這樣的GC則有助于科學驗證優化。
如何啟用epsilon GC
JVM工程師特別注意不要在生產中默認啟用此GC,因此要使用此GC,我們必須使用以下JVM選項
-XX:+ UnlockExperimentalVMOptions -XX:+ UseEpsilonGC -Xlog:gc
您可能會想到的一個問題是,內存耗盡時會發生什么? JVM將因內存不足錯誤而停止。
讓我們看一些代碼來測試GC
如何知道JVM進程中是否使用epsilon?
Java具有良好的管理API,可以查詢正在使用的當前GC,也可以用來驗證不同版本的Java中的默認GC是什么。
public class VerifyCurrentGC { ? public static void main(String... args) { ? var gcBeans = ManagementFactory.getGarbageCollectorMXBeans(); ? gcBeans.stream().forEach(gc -> { ? out.println(format( "GC Name : %s" , gc.getName())); var poolNames = gc.getMemoryPoolNames(); if (poolNames != null ) { List.of(poolNames).forEach(pool -> out.println(format( "Pool name %s" , pool))); } else { out.println( "No memory pools for " + gc.getName()); "No memory pools for " + gc.getName()); } ? }); ? } } 使用以下選項運行以上代碼
-XX:+ UnlockExperimentalVMOptions -XX:+ UseEpsilonGC VerifyCurrentGC 內存耗盡時代碼的行為方式。
我將使用下面的代碼來展示新GC的工作方式。
public class MemoryAllocator { ? public static final int KB = 1024 ; static int mbToAllocate = Integer.getInteger( "mb" , 1000 ); ? public static void main(String[] args) { System.out.println(String.format( "Start allocation of %s MBs" , mbToAllocate)); ? for (var i = 0 ; i < mbToAllocate; i++) { var garbage = new byte [KB * KB]; } ? System.out.println( "I was Alive after allocation" ); } }使用默認的GC運行以上代碼并請求5GB分配不會引起任何問題( java -Xlog:gc -Dmb = 5024 MemoryAllocator ),并且它會產生以下輸出
[0.016s] [info] [gc]使用G1
[0.041s] [info] [gc]定期GC已禁用
開始分配5024 MB [0.197s] [info] [gc] GC(0)暫停年輕(并發啟動)(G1大量分配)116M-> 0M(254M)3.286ms [0.197s] [info] [gc] GC(1)并發周期 [0.203s] [info] [gc] GC(1)暫停備注20M-> 20M(70M)4.387ms [0.203s] [info] [gc] GC(1)暫停清理22M-> 22M(70M)0.043ms [1.600s] [info] [gc] GC(397)并發周期6.612ms [1.601s] [info] [gc] GC(398)暫停年輕(并發啟動)(G1混合分配)52M-> 0M(117M)1.073ms [1.601s] [info] [gc] GC(399)并發周期 分配后我還活著 [1.606s] [info] [gc] GC(399)暫停備注35M-> 35M(117M)0.382ms [1.607s] [info] [gc] GC(399)暫停清理35M-> 35M(117M)0.093ms [1.607s] [info] [gc] GC(399)并發周期6.062ms
讓我們添加一些內存限制( java -XX:+ UnlockExperimentalVMOptions -XX:+ UseEpsilonGC -Xlog:gc -Xmx1g -Dmb = 5024
內存分配器)
[0.011s] [info] [gc]可調整大小的堆; 從253M開始,最大:1024M,步長:128M [0.011s] [info] [gc]使用TLAB分配; 最高:4096K [0.011s] [info] [gc]啟用了彈性TLAB; 彈性:1.10倍 [0.011s] [info] [gc]啟用了彈性TLAB衰減; 衰減時間:1000ms [0.011s] [info] [gc]使用Epsilon 開始分配5024 MB [0.147s] [info] [gc]堆:已保留1024M,已提交253M(24.77%),已使用52640K(5.02%) [0.171s] [info] [gc]堆:已保留1024M,已承諾253M(24.77%),已使用103M(10.10%) [0.579s] [info] [gc]堆:已保留1024M,已落實1021M(99.77%),已使用935M(91.35%) [0.605s] [info] [gc]堆:已使用1024M,已承諾1021M(99.77%),已使用987M(96.43%)
由于java.lang.OutOfMemoryError而終止:Java堆空間
此特定運行導??致OOM錯誤,可以很好地確認1GB之后該程序將崩潰。
真正的多線程程序也具有相同的行為,請參考MultiThreadMemoryAllocator.java以獲取示例。
單元測試可用于測試此特殊GC的功能。
我認為Epsilon將來會發現更多用例和采用情況,這絕對是增加JVM覆蓋率的好一步。
所有代碼示例均可用Github回購
如果您喜歡該職位,則可以在Twitter上關注我 。
翻譯自: https://www.javacodegeeks.com/2019/08/jvm-with-no-garbage-collection.html
總結
以上是生活随笔為你收集整理的没有垃圾回收的JVM的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Zing加快了JVM应用程序的预热
- 下一篇: 数据类被认为有害