Java 虚拟机需要内存来呼吸——有时比我们喜欢的还要多。Metaspace 是它最需要的子系统之一,它是 JVM 中保存类元数据的部分。通过 JEP 387,SAP 为 OpenJDK 贡献了一个更加节俭和弹性的实现。
尽管“弹性元空间”相对默默无闻,但它是此版本最大的外部贡献之一,补丁本身的数量高达 25kloc。
什么是 JEP?
Java(Java 虚拟机和 JDK)是在OpenJDK 的保护伞下开发的,OpenJDK 是一个由 Oracle 和其他公司管理的大型开源项目。SAP 一直是该项目的长期贡献者,我们第一次参与可以追溯到 2012 年。
OpenJDK 开发由流程管理,正常的增强通过一个称为增强请求 (RFE) 的过程。RFE 需要补丁审查,但通常很少,除非补丁影响兼容性。
但是对 JVM、Java 语言或 JDK 的 API 表面的重大更改扩展了 RFE 的范围。因此,它们受制于更重量级的Java Enhancement Proposal 过程(在漂亮的递归中,它由其自己的 JEP定义)。JEP 需要更广泛的设计和代码审查。因此,它通常比简单的 RFE 需要更长的时间。尽管如此,JEP 对于确保 JDK 的长期质量和兼容性至关重要。
大多数 JEP 都是 Oracle 自己完成的,尽管该过程对所有人开放。这可能归结为纯粹的人才库规模。但是在 JEP 之外是可能的并且已经完成:例如,在 2019 年,Red Hat 提供了他们著名的 Shenandoah-GC 作为 JEP 189。
堆外内存和元空间
JVM 可能是一个资源匮乏的野兽。最大的内存消耗者通常是 Java 堆,可以说这很好,也是预期的,因为它包含实际的程序数据。其他一切都只是必要的过剩——使机器运转所需的油脂。
因此,用户有时会惊讶地发现 Java 堆消耗只是 JVM 进程总占用空间的一部分。但是我们需要容纳很多内部数据,例如:
- 线程栈
- GC 控制结构
- 实习字符串
- CDS 档案和文本片段
- JIT 编译的代码(代码缓存)
- 还有很多很多其他的东西
所有这些数据都位于 Java 堆之外,无论是在 C 堆中还是在手动管理的映射中。通俗地称为堆外(或者更不正确地称为本机)内存,这些区域的组合大