在 Java 8 堆打印输出中,您可能会看到一行如下所示:
Metaspace used 2425K, capacity 4498K, committed 4864K, reserved 1056768K
https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/considerations.html试图解释这一行:
In the line beginning with Metaspace, the used value is the amount of space used for loaded classes. The capacity value is the space available for metadata in currently allocated chunks. The committed value is the amount of space available for chunks. The reserved value is the amount of space reserved (but not necessarily committed) for metadata.
同样,从上面的链接:
Space is requested from the OS and then divided into chunks. A class loader allocates space for metadata from its chunks (a chunk is bound to a specific class loader).
我想知道每个字段的含义(used、capacity、committed、reserved),但我很难理解上面的定义。
我的理解是,元空间是从 JVM 进程的虚拟地址空间中划分出来的。 JVM 在启动时根据 -XX:MetaspaceSize 保留一个初始大小,它有一个未记录的、特定于平台的默认值。我假设 reserved 是指元空间的总大小。空间被分成 block 。我不确定每个 block 是否具有相同的大小。每个 block 都包含与单个类加载器关联的类元数据。
Capacity 和 committed 对我来说听起来像是自由空间(基于链接中的定义)。由于元数据存储在 block 中,因此我假设已用 + 容量等于已提交,但事实并非如此。也许提交意味着使用的保留空间,但是使用意味着什么?元数据使用的已用空间?那么,还有哪些其他的空间利用方式呢?
我希望你看到我的困惑。我将不胜感激对定义的澄清。
最佳答案
元空间由一个或多个虚拟空间组成。虚拟空间是从操作系统获得的连续地址空间区域。它们是按需分配的。分配后,虚拟空间从操作系统保留内存,但尚未提交。元空间保留内存是所有虚拟空间的总大小。
Virtual Space 内部的分配单元是 Metachunk(或简称为 Chunk)。当从虚拟空间分配新 block 时,相应的内存将提交。元空间提交内存是所有 block 的总大小。
block 的大小可能不同。当一个 ClassLoader 被垃圾回收时,属于它的所有 Metachunks 都被释放。空闲 block 保存在全局空闲列表中。元空间容量是所有分配(即非空闲) block 的总大小。
新 block 分配
- 在空闲列表中查找现有的空闲 block 。
- 如果没有合适的空闲 block ,从当前虚拟空间分配一个新 block 。
- 如果当前的虚拟空间用完了,保留一个新的虚拟空间。
类元数据在 block 内分配。 Chunk 可能不包含来自多个 ClassLoader 的数据,但一个 ClassLoader 可能有多个 chunk。 Metaspace used 是所有 block 中所有类元数据的总大小。
关于java - 了解 JVM 堆打印输出中的元空间行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40891433/