1

对于 Java 8 之后的 JVM

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

2 回答 2

3

首先,“元空间的大小”是模棱两可的,因此没有上下文就毫无意义。至少有五个指标:reservedcommitted容量和已内存,如本答案中所述,以及高水位线,也称为capacity_until_gc

元空间布局

元空间不仅仅是一个连续的内存区域,因此它不会按照常识调整大小。相反,当分配发生时,上述一项或多项指标会发生变化。

  1. 在最快的路径上,从当前块中分配一个元数据块。used在这种情况下,内存会增加,仅此而已。
  2. 如果当前块中没有足够的空间,JVM 会搜索一个可能空闲的现有块。如果它成功重用块,则capacity增加。在此之前不会发生 GC。
  3. 如果没有空闲块,JVM 会尝试提交更多内存,除非新committed大小超过capacity_until_gc.
  4. 如果capacity_until_gc达到阈值,JVM 会触发 GC 循环。
  5. 如果 GC 没有释放足够的内存,则会增加高水位线,以便分配另一个虚拟空间。

在 GC 之后,根据以下 JVM 标志调整高水位标记值:

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

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

于 2019-07-26T01:00:22.007 回答
2

您可以配置元空间大小,但 JVM 可以根据依赖的平台增加或减少大小。请参阅Oracle 文档。

-XX:元空间大小=大小

设置分配的类元数据空间的大小,第一次超出时将触发垃圾收集。垃圾收集的阈值根据使用的元数据量增加或减少。默认大小取决于平台。

于 2019-07-24T07:19:13.080 回答