没有垃圾回收的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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值