21

在 Java 8 堆打印输出中,您可能会看到如下所示的一行:

元空间已用2425K ,容量4498K,已提交4864K,保留1056768K

https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/considerations.html试图解释这一行:

在以 Metaspace 开头的行中,使用的值是用于加载的类的空间量。容量值是当前分配的块中可用于元数据的空间。提交的值是可用于块的空间量。保留值是为元数据保留(但不一定提交)的空间量。

同样,从上面的链接:

从操作系统请求空间,然后分成块。类加载器从其块中为元数据分配空间(块绑定到特定的类加载器)。

我想知道每个字段的含义(已使用、容量、已提交、保留),但我很难理解上述定义。

我的理解是元空间是从 JVM 进程的虚拟地址空间中分割出​​来的。JVM 在启动时根据 -XX:MetaspaceSize 保留初始大小,该大小具有未记录的特定于平台的默认值。我假设reserved是指元空间的总大小。空间被分成块。我不确定每个块是否具有相同的大小。每个块包含与单个类加载器关联的类元数据。

容量承诺对我来说听起来像是可用空间(基于链接中的定义)。由于元数据存储在块中,所以我假设已用 + 容量将等于已提交,但事实并非如此。也许已提交意味着已使用的保留空间,但是使用的意思是什么?元数据使用的空间?那么,还有什么其他方式可以利用空间呢?

我希望你能看到我的困惑。我希望澄清定义。

4

1 回答 1

50

元空间布局

元空间由一个或多个虚拟空间组成。虚拟空间是从操作系统获得的连续地址空间区域。它们是按需分配的。分配后,虚拟空间会从操作系统保留内存,但尚未提交。元空间保留内存是所有虚拟空间的总大小。

虚拟空间内的分配单元是 Metachunk(或简称为 Chunk)。当从虚拟空间分配新块时,会提交相应的内存。元空间提交的内存是所有块的总大小。

块的大小可能不同。当 ClassLoader 被垃圾回收时,属于它的所有 Metachunk 都会被释放。空闲块在全局空闲列表中维护。元空间容量是所有已分配(即非空闲)块的总大小。

新的块分配

  1. 在空闲列表中查找现有的空闲块。
  2. 如果没有合适的空闲块,则从当前虚拟空间中分配一个新块。
  3. 如果当前虚拟空间已用尽,则保留一个新的虚拟空间。

类元数据在一个块内分配。Chunk 可能不包含来自多个 ClassLoader 的数据,但一个 ClassLoader 可能有多个 chunk。使用的元空间是来自所有块的所有类元数据的总大小

于 2016-11-30T23:15:44.780 回答