JVM元空间在调整大小时是否总是触发GC

Does JVM metaspace always trigger GC when resizing

对于 Java 8

之后的 JVM
  1. 当metaspace的大小>-XX:metaspaceSize时,会触发gc。
  2. 无论-XX:metaspaceSize-XX:maxMetaspaceSize如何配置,元空间的初始大小在64位服务器上通常是一个固定值(20.8M)。
  3. JVM 将在接近当前容量时自动调整元空间大小。
  4. 那么,如果-XX:metaspaceSize例如是20G,当前metaspace的大小是18M,需要分配大量的新对象(大约100M),JVM必须为这些新的对象调整metaspace的大小对象,JVM 会在调整大小之前触发完整的 GC 吗?

您可以配置元空间大小,但 JVM 可以根据相关平台增加或减少大小。 参见 Oracle docs.

-XX:MetaspaceSize=size

Sets the size of the allocated class metadata space that will trigger a garbage collection the first time it is exceeded. This threshold for a garbage collection is increased or decreased depending on the amount of metadata used. The default size depends on the platform.

首先,"the size of the metaspace"是模棱两可的,因此没有上下文就没有意义。至少有五个指标:reservedcommittedcapacityused 内存如 中所述,以及 high-water 标记,也称为 capacity_until_gc.

Metaspace 不仅仅是一个连续的内存区域,所以它不会按常识调整大小。相反,当分配发生时,上述一个或多个指标会发生变化。

  1. 在最快的路径上,从当前块中分配一块元数据。 used本例内存增加,仅此而已。
  2. 如果当前块中没有足够的空间,JVM 会搜索可能空闲的现有块。如果成功重用块,capacity 增加。直到此时才发生 GC。
  3. 如果没有空闲块,JVM 会尝试提交更多内存,除非新的 committed 大小会超过 capacity_until_gc
  4. 如果达到 capacity_until_gc 阈值,JVM 将触发 GC 周期。
  5. 如果 GC 没有释放足够的内存,high-water 标记会增加,以便分配另一个虚拟 Space。

GC后high-water标记值根据following JVM flags调整:

  • -XX:MinMetaspaceFreeRatio(用于计算metaspace容量中需要多少空闲space来决定增加多少HWM);
  • -XX:MaxMetaspaceFreeRatio(用于决定在降低 HWM 之前元space 容量中需要多少空闲 space);
  • -XX:MinMetaspaceExpansion(Metaspace的最小扩展字节数);
  • -XX:MaxMetaspaceExpansion(没有full GC的Metaspace的最大扩展)。

TL;DR没那么简单。 JVM 绝对可以在不触发 GC 的情况下提交更多 Metaspace 内存。但是,当达到HWM时,会触发GC,根据人机工程学策略重新计算HWM。