跳到主要内容

JEP 304:垃圾收集器接口

概括

通过引入干净的垃圾收集器 (GC) 接口,提高不同垃圾收集器的源代码隔离。

目标

  • HotSpot 内部 GC 代码的模块化程度更高
  • 更简单地向 HotSpot 添加新的 GC,而不会干扰当前的代码库
  • 更容易从 JDK 构建中排除 GC

非目标

  • 实际添加或删除 GC 并不是目标。
  • 这项工作将在 HotSpot 中 GC 算法的构建时隔离方面取得进展,但并不是_完全_实现构建时隔离(即另一个 JEP)的目标。

成功指标

  • 如果 GC 实现大部分包含在各自src/hotspot/share/gc/$NAME目录和潜在src/hotspot/cpu/share/gc/$NAME目录中的源文件中,则该实现将被视为成功。这些目录之外的最少代码应包含这些目录内的文件,并且应该很少有 GC 特定的if分支else
  • 性能不应因此次重构而下降。

动机

当前,每个垃圾收集器实现都由其目录内的源文件组成src/hotspot/share/gc/$NAME,例如 G1 位于 中src/hotspot/share/gc/g1,CMS 位于src/hotspot/share/gc/cms等中。但是,HotSpot 源中到处都散布着一些碎片。例如,大多数GC都需要一定的屏障,这些屏障需要在运行时、解释器、C1和C2中实现。这些屏障并不包含在 GC 的特定目录中,而是在共享解释器、C1 和 C2 源代码中实现(通常由长链保护ifelse。同样的问题也适用于诊断代码,例如MemoryMXBeans.这种源代码布局有几个缺点:

  1. 对于 GC 开发人员来说,实现新的垃圾收集器需要了解所有这些不同的地方,以及如何扩展它们以满足他们的特定需求。
  2. 对于不是 GC 开发人员的 HotSpot 开发人员来说,在哪里可以找到给定 GC 的特定代码段是令人困惑的。
  3. 在构建时很难排除特定的垃圾收集器。长期以来#define INCLUDE_ALL_GCS,一直有一种构建仅内置串行收集器的 JVM 的方法,但这种机制变得过于不灵活。

更干净的 GC 接口将使实现新收集器变得更加容易,它将使代码更加干净,并且更容易在构建时排除一个或多个收集器。添加新的垃圾收集器应该是实现一组记录良好的接口的问题,而不是找出 HotSpot 中需要更改的所有位置。

描述

CollectedHeapGC 接口将由每个垃圾收集器需要实现的现有类定义。该类CollectedHeap将驱动垃圾收集器和 HotSpot 其余部分之间交互的大部分方面(在实例化之前需要一些实用程序类CollectedHeap)。更具体地说,垃圾收集器实现必须提供:

  • 堆,一个子类CollectedHeap
  • 障碍集, 的子类BarrierSet,它实现了运行时的各种障碍
  • 一个实现CollectorPolicy
  • 的实现GCInterpreterSupport,它为解释器实现了 GC 的各种障碍(使用汇编指令)
  • 的实现GCC1Support,它为 C1 编译器实现了 GC 的各种障碍
  • 的实现GCC2Support,它为 C2 编译器实现了 GC 的各种障碍
  • 最终 GC 特定参数的初始化
  • 设置a MemoryService、相关的内存池、内存管理器等。

在多个垃圾收集器之间共享的实现细节的代码应该存在于辅助类中。这样,不同的 GC 实现就可以轻松地使用它。例如,可能有一个帮助程序类实现了卡表支持的各种障碍,并且任何需要卡表后障碍的 GC 都会调用该帮助程序类的相应方法。通过这种方式,该接口可以灵活地实现全新的障碍,同时允许以混合搭配的方式重用现有代码。

备择方案

另一种选择是继续使用当前的架构。这很可能会持续更长的时间,但会阻碍未来新 GC 算法的开发和旧算法的删除。

测试

这纯粹是重构。之前有效的一切都需要在之后有效,并且性能不应该倒退。运行标准回归测试套件就足够了;无需开发新的测试。

风险和假设

风险较低,这主要是HotSpot内部代码的重构。存在性能可能受到损害的风险,例如,如果引入额外的虚拟呼叫。这种风险可以通过持续的性能测试来减轻。

依赖关系

此 JEP 将有助于JEP 291:弃用并发标记扫描 (CMS) 垃圾收集器,因为它提供了一种隔离它的方法,并允许其他人在需要时对其进行维护。

此 JEP 还将​​帮助JEP 189:Shenandoah:超低暂停时间垃圾收集器,并使其更改不那么具有侵入性。