了解 JVM 堆打印输出中的元空间行

2022-09-02 02:43:34

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

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

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

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

同样,从上面的链接:

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

我想知道每个字段的含义(使用,容量,承诺,保留),但我正在努力理解上述定义。

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

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

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


答案 1

Metaspace layout

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

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

块的大小可能不同。当类加载器被垃圾收集时,属于它的所有Metachunk都会被释放。免费块保留在全局免费列表中。元空间容量是所有已分配(即非空闲)块的总大小。

新的区块分配

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

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


答案 2

推荐