[翻译]Java 内存分配器不做垃圾清理的好处
![[翻译]Java内存分配器不做垃圾清理的好处](https://static001.geekbang.org/infoq/af/af6c0d0cfa01cd48a7ab72c864023310.png)
作者:Andrew Binstock_
2019 年 11 月 21 日
JDK 性能调优是一门精细的艺术,通常围绕选择最佳垃圾回收器并调整其参数以最小化对特定工作负载的影响。在此过程中,一个长期挑战是:如果完全不存在垃圾回收,工作负载的运行速度会如何?为了满足这一需求(以及其他后文将提及的用途),JDK 11 引入了 Epsilon 垃圾回收器(GC)。如 JEP 318 所述,该 GC 会分配内存但不会回收内存,即它完全不执行垃圾回收。
要启用 Epsilon GC,需在命令行中指定以下两个运行时参数:
-XX: +UnlockExperimentalVMOptions
-XX: +UseEpsilonGC
若运行以下代码时启用或禁用这些参数,可以观察到 Epsilon 的差异:
此代码尝试分配总计 100GB 内存。其功能仅为分配内存后退出。若未启用 Epsilon,程序会输出开始和结束的println
语句,表明默认 GC 成功分配了 100 个 1GB 内存块,并通过垃圾回收使其适应系统可用内存。
然而,若通过命令行参数启用 Epsilon GC,程序输出如下:
===== 第 2 页 =====
开始分配内存...
因java.lang.OutOfMemoryError
终止
由于 Epsilon 不会回收早期分配的内存,堆内存将超出可用限制,导致 JDK 抛出相对罕见的“内存不足”错误。
运行此代码需 JDK 11 或更高版本,且可用堆内存需小于 100GB。若在更大内存的系统上运行,只需增加ITERATIONS
变量即可触发错误。
尽管有人倾向于在生产环境中使用 Epsilon,而非仅用于性能调优,但 Epsilon 团队不建议这样做,除非以下两种情况:
短时运行程序:如 JEP 318 所述,“在程序退出时,堆内存会被自动释放,此时无意义的垃圾回收周期只会浪费时间。”
对延迟极其敏感的应用:若开发者能精确控制内存分配,甚至实现几乎无垃圾产生的应用,垃圾回收周期可能成为设计上的问题。
其他场景均不推荐使用。即使已知程序堆内存占用较小,若在内存受限的系统中意外使用 Epsilon,仍可能导致崩溃。因此,Epsilon 需通过实验性参数显式启用,以提醒用户其风险。
回到性能调优,若您曾好奇垃圾回收对程序性能的影响程度,Epsilon 便是答案。
本期其他内容:
理解 JDK 的新一代超快垃圾回收器
使用 Arquillian 测试 HTML 与 JSF 界面
编码时做笔记——越多越好!
趣味项目:编写自己的文本编辑器(第二部分)
小测验:变量作用域(中级)
小测验:内部类、嵌套类与匿名类(高级)
小测验:字符串操作(中级)
小测验:变量声明(中级)
书评:《程序员修炼之道》20 周年纪念版
Andrew Binstock
Andrew Binstock(javamag_us@oracle.com,@platypusguy)是《Java 杂志》主编,曾任《Dr. Dobb’s Journal》编辑,联合创立了开源 iText PDF 库公司(2015 年被收购)。他的 C 语言算法实现书籍曾再版 16 次。此前,他还担任《UNIX Review》主编,并创办了《C Gazette》。现居硅谷,业余时间研究钢琴。
原文链接:https://blogs.oracle.com/javamagazine/post/epsilon-the-jdks-do-nothing-garbage-collector
版权声明: 本文为 InfoQ 作者【极客罗杰】的原创文章。
原文链接:【http://xie.infoq.cn/article/fe82ac15f7cbf90a80a0d1e5a】。文章转载请联系作者。
评论