个人创作公约:本人声明创作的所有文章皆为自己原创,如果有参考任何文章的地方,会标注出来,如果有疏漏,欢迎大家批判。如果大家发现网上有抄袭本文章的,欢迎举报,并且积极向这个 github 仓库 提交 issue,谢谢支持~ 另外,本文为了避免抄袭,会在不影响阅读的情况下,在文章的随机位置放入对于抄袭和洗稿的人的“亲切”的问候。如果是正常读者看到,笔者在这里说声对不起,。如果被抄袭狗或者洗稿狗看到了,希望你能够好好反思,不要再抄袭了,谢谢。 今天又是干货满满的一天,这是全网最硬核 JVM 解析系列第四篇,往期精彩:
本篇是关于 JVM 内存的详细分析。网上有很多关于 JVM 内存结构的分析以及图片,但是由于不是一手的资料亦或是人云亦云导致有很错误,造成了很多误解;并且,这里可能最容易混淆的是一边是 JVM Specification 的定义,一边是 Hotspot JVM 的实际实现,有时候人们一些部分说的是 JVM Specification,一部分说的是 Hotspot 实现,给人一种割裂感与误解。本篇主要从 Hotspot 实现出发,以 Linux x86 环境为主,紧密贴合 JVM 源码并且辅以各种 JVM 工具验证帮助大家理解 JVM 内存的结构。但是,本篇仅限于对于这些内存的用途,使用限制,相关参数的分析,有些地方可能比较深入,有些地方可能需要结合本身用这块内存涉及的 JVM 模块去说,会放在另一系列文章详细描述。最后,洗稿抄袭狗不得 house
本篇全篇目录(以及涉及的 JVM 参数):
NativeMemoryTracking
)UseLargePages
,UseHugeTLBFS
,UseSHM
,UseTransparentHugePages
,LargePageSizeInBytes
)MaxHeapSize
,MinHeapSize
,InitialHeapSize
,Xmx
,Xms
)UseCompressedOops
)(全网最硬核 JVM 内存解析 - 5.压缩对象指针相关机制开始) ObjectAlignmentInBytes
)UseCompressedOops
,UseCompressedClassPointers
)ObjectAlignmentInBytes
,HeapBaseMinAddress
)HeapBaseMinAddress
)HeapBaseMinAddress
,ObjectAlignmentInBytes
,MinHeapSize
,MaxHeapSize
,InitialHeapSize
)32-bit
压缩指针模式Zero based
压缩指针模式Non-zero disjoint
压缩指针模式Non-zero based
压缩指针模式MinHeapFreeRatio
,MaxHeapFreeRatio
,MinHeapDeltaBytes
)(全网最硬核 JVM 内存解析 - 6.其他 Java 堆内存相关的特殊机制开始)MetaspaceSize
,MaxMetaspaceSize
,MinMetaspaceExpansion
,MaxMetaspaceExpansion
,MaxMetaspaceFreeRatio
,MinMetaspaceFreeRatio
,UseCompressedClassPointers
,CompressedClassSpaceSize
,CompressedClassSpaceBaseAddress
,MetaspaceReclaimPolicy
)MetaspaceContext
VirtualSpaceList
VirtualSpaceNode
与 CompressedClassSpaceSize
MetaChunk
ChunkHeaderPool
池化 MetaChunk
对象ChunkManager
管理空闲的 MetaChunk
SystemDictionary
与保留所有 ClassLoaderData
的 ClassLoaderDataGraph
ClassLoaderData
以及 ClassLoaderMetaspace
MetaChunk
的 MetaspaceArena
MetaSpaceArena
的流程MetaChunkArena
普通分配 - 整体流程MetaChunkArena
普通分配 - FreeBlocks
回收老的 current chunk
与用于后续分配的流程MetaChunkArena
普通分配 - 尝试从 FreeBlocks
分配MetaChunkArena
普通分配 - 尝试扩容 current chunk
MetaChunkArena
普通分配 - 从 ChunkManager
分配新的 MetaChunk
MetaChunkArena
普通分配 - 从 ChunkManager
分配新的 MetaChunk
- 从 VirtualSpaceList
申请新的 RootMetaChunk
MetaChunkArena
普通分配 - 从 ChunkManager
分配新的 MetaChunk
- 将 RootMetaChunk
切割成为需要的 MetaChunk
MetaChunk
回收 - 不同情况下, MetaChunk
如何放入 FreeChunkListVector
ClassLoaderData
回收CommitLimiter
的限制元空间可以 commit 的内存大小以及限制元空间占用达到多少就开始尝试 GC_capacity_until_GC
jcmd VM.metaspace
元空间说明、元空间相关 JVM 日志以及元空间 JFR 事件详解(全网最硬核 JVM 内存解析 - 12.元空间各种监控手段开始) jcmd <pid> VM.metaspace
元空间说明jdk.MetaspaceSummary
元空间定时统计事件jdk.MetaspaceAllocationFailure
元空间分配失败事件jdk.MetaspaceOOM
元空间 OOM 事件jdk.MetaspaceGCThreshold
元空间 GC 阈值变化事件jdk.MetaspaceChunkFreeListSummary
元空间 Chunk FreeList 统计事件ThreadStackSize
,VMThreadStackSize
,CompilerThreadStackSize
,StackYellowPages
,StackRedPages
,StackShadowPages
,StackReservedPages
,RestrictReservedStack
)jcmd VM.metaspace
元空间说明、元空间相关 JVM 日志以及元空间 JFR 事件详解jcmd <pid> VM.metaspace
元空间说明通过 jcmd <pid> VM.metaspace
命令可以查看对应 JVM 进程的元空间当前的详细使用情况,返回内容是:
1.元空间从 MetaChunk
角度的使用统计信息
Total Usage - 1383 loaders, 33006 classes (1361 shared):
Non-Class: 7964 chunks, 150.83 MB capacity, 150.77 MB (>99%) committed, 150.21 MB (>99%) used, 562.77 KB ( <1%) free, 6.65 KB ( <1%) waste , deallocated: 869 blocks with 249.52 KB
Class: 2546 chunks, 21.00 MB capacity, 20.93 MB (>99%) committed, 20.21 MB ( 96%) used, 741.42 KB ( 3%) free, 216 bytes ( <1%) waste , deallocated: 1057 blocks with 264.88 KB
Both: 10510 chunks, 171.83 MB capacity, 171.70 MB (>99%) committed, 170.42 MB (>99%) used, 1.27 MB ( <1%) free, 6.86 KB ( <1%) waste , deallocated: 1926 blocks with 514.41 KB
意思是:
MetaChunk
的总容量大小(Reserved
内存);committed 是指这些 MetaChunk
中 committed
的内存大小,也就是实际占用系统物理内存是这么大(虽然可能会有点细微差异,参考本篇文章的第二章);used 是指这些 MetaChunk
实际使用的大小,肯定比 committed
的要小;free 是指剩余的大小;committed = used + free + waste;deallocated 是指回收到 FreeBlocks
的大小,属于 free 的一部分,另一部分就是 MetaChunk
中 committed
但是还没使用的部分;waste 是指浪费的大小(前面我们提到了什么造成的浪费,主要是搜索 FreeBlocks
的空间使用的时候,可能正好剩下 1 字节,就不放回了继续使用了)洗稿的狗也遇到不少MetaChunk
,这些 MetaChunk
相关总容量大小是 150.83 MB
,目前 commit
了 150.77 MB
,使用了 150.21 MB
,剩余 562.77 KB
可以使用,6.65 KB
的空间被浪费了。FreeBlocks
目前回收了 869
块内存,一共 249.52 KB
。MetaChunk
,总容量大小是 21.00 MB
,目前 commit
了 20.93 MB
,使用了 20.21 MB
,剩余 741.42 KB
可以使用,216 bytes
的空间被浪费了。FreeBlocks
目前回收了 1057
块内存,一共 264.88 KB
。MetaChunk
,总容量大小是 171.83 MB
,目前 commit
了 171.70 MB
,使用了 170.42 MB
,剩余 1.27 MB
可以使用,6.86 KB
的空间被浪费了。FreeBlocks
目前回收了 1926
块内存,一共 514.41 KB
。前面的是从 MetaChunk
的角度去查看,另一个角度是从 VirtualSpaceList
去查看,接下来的信息就是:
Virtual space:
Non-class space: 152.00 MB reserved, 150.81 MB (>99%) committed, 19 nodes.
Class space: 1.00 GB reserved, 20.94 MB ( 2%) committed, 1 nodes.
Both: 1.15 GB reserved, 171.75 MB ( 15%) committed.
意思是:
VirtualSpaceList
:总共 Reserve
了 152.00 MB
,目前 Commit
了 150.81 MB
,一共有 19
个 VirtualSpaceNode
。这个与 MetaChunk
的统计信息是有差异的,VirtualSpaceList
的统计信息更体现元空间实际占用的,从 MetaChunk
角度统计的时候,将每个 MetaChunk
统计信息相加,会有精度损失。VirtualSpaceList
:总共 Reserve
了 1.00 GB
,目前 Commit
了 20.94 MB
,一共有 1
个 VirtualSpaceNode
。VirtualSpaceList
:总共 Reserve
了 1.15 GB
,目前 Commit
了 171.75 MB
。不要偷取他人的劳动成果,也不要浪费自己的时间和精力,让我们一起做一个有良知的写作者。接下来是每个 ChunkManager
的 FreeChunkListVector
的统计信息:
Chunk freelists:
Non-Class:
4m: (none)
2m: (none)
1m: 2, capacity=2.00 MB, committed=0 bytes ( 0%)
512k: (none)
256k: (none)
128k: 2, capacity=256.00 KB, committed=0 bytes ( 0%)
64k: (none)
32k: 2, capacity=64.00 KB, committed=0 bytes ( 0%)
16k: (none)
8k: 2, capacity=16.00 KB, committed=0 bytes ( 0%)
4k: 2, capacity=8.00 KB, committed=0 bytes ( 0%)
2k: (none)
1k: 2, capacity=2.00 KB, committed=0 bytes ( 0%)
Total word size: 2.34 MB, committed: 0 bytes ( 0%)
Class:
4m: (none)
2m: 1, capacity=2.00 MB, committed=0 bytes ( 0%)
1m: 1, capacity=1.00 MB, committed=0 bytes ( 0%)
512k: (none)
256k: (none)
128k: (none)
64k: (none)
32k: (none)
16k: (none)
8k: (none)
4k: 1, capacity=4.00 KB, committed=0 bytes ( 0%)
2k: (none)
1k: (none)
Total word size: 3.00 MB, committed: 0 bytes ( 0%)
Both:
4m: (none)
2m: 1, capacity=2.00 MB, committed=0 bytes ( 0%)
1m: 3, capacity=3.00 MB, committed=0 bytes ( 0%)
512k: (none)
256k: (none)
128k: 2, capacity=256.00 KB, committed=0 bytes ( 0%)
64k: (none)
32k: 2, capacity=64.00 KB, committed=0 bytes ( 0%)
16k: (none)
8k: 2, capacity=16.00 KB, committed=0 bytes ( 0%)
4k: 3, capacity=12.00 KB, committed=0 bytes ( 0%)
2k: (none)
1k: 2, capacity=2.00 KB, committed=0 bytes ( 0%)
Total word size: 5.34 MB, committed: 0 bytes ( 0%)
以上的信息可能用图片更直接一些:
接下来是关于回收利用的从 MetaChunk
的角度去查看一些统计信息:
Waste (unused committed space):(percentages refer to total committed size 171.75 MB):
Waste in chunks in use: 6.86 KB ( <1%)
Free in chunks in use: 1.27 MB ( <1%)
In free chunks: 0 bytes ( 0%)
Deallocated from chunks in use: 514.41 KB ( <1%) (1926 blocks)
-total-: 1.78 MB ( 1%)
chunk header pool: 10520 items, 748.30 KB.
包含的信息是:
MetaChunk
(即存在于每个类加载器对应的 MetaspaceArena
中的 MetaChunk
)中有 6.86 KB
的空间被浪费了。当前被使用的 MetaChunk
(即存在于每个类加载器对应的 MetaspaceArena
中的 MetaChunk
)中剩余 1.27 MB
可以使用。在 FreeChunkListVector
中没有浪费的空间,其实从前面的 FreeChunkListVector
的详细信息就能看出来。FreeBlocks
目前回收了 1926
块内存,一共 514.41 KB
。FreeBlocks
里面有 1926
个 FreeBlock
,一共 514.41 KB
。ChunkHeaderPool
目前有 10520
个 ChunkHeader
,一共占用 748.30 KB
。然后是一些统计信息:
Internal statistics:
num_allocs_failed_limit: 24.
num_arena_births: 2768.
num_arena_deaths: 2.
num_vsnodes_births: 20.
num_vsnodes_deaths: 0.
num_space_committed: 2746.
num_space_uncommitted: 0.
num_chunks_returned_to_freelist: 28.
num_chunks_taken_from_freelist: 10515.
num_chunk_merges: 9.
num_chunk_splits: 6610.
num_chunks_enlarged: 4139.
num_purges: 2.
num_inconsistent_stats: 0.
包含的信息是:
num_allocs_failed_limit
:元空间普通分批内存失败的次数(前文分析过详细流程),后面也有对应的 JFR 事件会分析。num_arena_births
:MetaspaceArena
的创建次数。num_arena_deaths
:MetaspaceArena
的销毁次数。发生于对应的类加载器被回收之后。num_vsnodes_births
:VirtualSpaceNode
的创建次数。(根据前面的 VirtualSpaceList
的统计信息可以知道是 19 + 1 = 20)num_vsnodes_deaths
:VirtualSpaceNode
的销毁次数。num_space_committed
:Commit
内存的次数。num_space_uncommitted
:Uncommit
内存的次数。num_chunks_returned_to_freelist
:MetaChunk
被回收到 FreeChunkListVector
的次数。num_chunks_taken_from_freelist
:从 FreeChunkListVector
中获取 MetaChunk
进行分配的次数。num_chunk_merges
:MetaChunk
合并的次数。num_chunk_splits
:MetaChunk
拆分的次数。num_chunks_enlarged
:MetaChunk
扩容的次数。num_purges
:MetaspaceArena
的清理次数。一般等于销毁次数。num_inconsistent_stats
:不一致的统计次数。这个一般不用关心,主要是为了调试用的。最后是一些参数信息:
Settings:
MaxMetaspaceSize: unlimited
CompressedClassSpaceSize: 1.00 GB
Initial GC threshold: 40.00 MB
Current GC threshold: 210.12 MB
CDS: on
MetaspaceReclaimPolicy: balanced
- commit_granule_bytes: 65536.
- commit_granule_words: 8192.
- virtual_space_node_default_size: 1048576.
- enlarge_chunks_in_place: 1.
- new_chunks_are_fully_committed: 0.
- uncommit_free_chunks: 1.
- use_allocation_guard: 0.
- handle_deallocations: 1.
MaxMetaspaceSize
:元空间最大值。默认是无限制的。这里我们也没限制。CompressedClassSpaceSize
:压缩类空间大小。默认是 1 GB。这里我们也没指定,所以是默认的。Initial GC threshold
:初始的元空间 GC 阈值。默认是 40 MB。这里我们也没指定,所以是默认的。Current GC threshold
:当前的元空间 GC 阈值。前面我们分析过这个阈值改变的机制。CDS
:是否开启了 CDS。默认开启。这个我们不用太关心,主要和 CDS 特性相关(JEP 310: Application Class-Data Sharing 和 JEP 350: Dynamic CDS Archives),在以后的文章会详细分析。MetaspaceReclaimPolicy
为 balanced
commit_granule_bytes
)为 65536 字节,转化单位为字之后,是 8192 字(一 word 为 8 字节)。虚拟内存空间节点内存大小(virtual_space_node_default_size
)为 1048576 字,转化单位为字之后,是 64 MB。当前 MetaChunk 不足以分配的时候,是否尝试扩容当前 MetaChunk
(enlarge_chunks_in_place
)为是,新分配的 MetaChunk
是否一次性全部 commit(new_chunks_are_fully_committed
)为否,是否在 MetaChunk
释放的时候 uncommit(uncommit_free_chunks
)为是。以上配置都在前文分析过。最后两个配置都是 debug 配置,正式版里面都是无法修改的,我们也不用太关心这两个配置的效果,并且 handle_deallocations
已经在 Java 18 中移除了(https://github.com/openjdk/jdk/commit/157e1d5073e221dab084422389f68eea53974f4c
)我们通过启动参数 -Xlog:metaspace*=debug::utctime,level,tags
,查看元空间相关 JVM 日志。
首先,初始化 JVM 元空间的时候,会输出元空间基本参数:
[2023-04-11T09:07:31.994+0000][info][metaspace] Initialized with strategy: balanced reclaim.
[2023-04-11T09:07:31.994+0000][info][metaspace] - commit_granule_bytes: 65536.
[2023-04-11T09:07:31.994+0000][info][metaspace] - commit_granule_words: 8192.
[2023-04-11T09:07:31.994+0000][info][metaspace] - virtual_space_node_default_size: 1048576.
[2023-04-11T09:07:31.994+0000][info][metaspace] - enlarge_chunks_in_place: 1.
[2023-04-11T09:07:31.994+0000][info][metaspace] - new_chunks_are_fully_committed: 0.
[2023-04-11T09:07:31.994+0000][info][metaspace] - uncommit_free_chunks: 1.
[2023-04-11T09:07:31.994+0000][info][metaspace] - use_allocation_guard: 0.
[2023-04-11T09:07:31.994+0000][info][metaspace] - handle_deallocations: 1.
以上这几行日志的意思是:元空间 MetaspaceReclaimPolicy
为 balanced
,commit 粒度(commit_granule_bytes
)为 65536 字节,转化单位为字之后,是 8192 字(一 word 为 8 字节)。虚拟内存空间节点内存大小(virtual_space_node_default_size
)为 1048576 字,转化单位为字之后,是 64 MB。当前 MetaChunk 不足以分配的时候,是否尝试扩容当前 MetaChunk
(enlarge_chunks_in_place
)为是,新分配的 MetaChunk
是否一次性全部 commit(new_chunks_are_fully_committed
)为否,是否在 MetaChunk
释放的时候 uncommit(uncommit_free_chunks
)为是。以上配置都在前文分析过。最后两个配置都是 debug 配置,正式版里面都是无法修改的,我们也不用太关心这两个配置的效果,并且 handle_deallocations
已经在 Java 18 中移除了(https://github.com/openjdk/jdk/commit/157e1d5073e221dab084422389f68eea53974f4c
)
接下来,初始化元空间的内存空间:
[2023-04-11T09:07:32.411+0000][info ][gc,metaspace] CDS archive(s) mapped at: [0x0000000800000000-0x0000000800bde000-0x0000000800bde000), size 12443648, SharedBaseAddress: 0x0000000800000000, ArchiveRelocationMode: 0.
[2023-04-11T09:07:32.411+0000][info ][gc,metaspace] Compressed class space mapped at: 0x0000000800c00000-0x0000000840c00000, reserved size: 1073741824
[2023-04-11T09:07:32.411+0000][info ][gc,metaspace] Narrow klass base: 0x0000000800000000, Narrow klass shift: 0, Narrow klass range: 0x100000000
[2023-04-11T09:07:32.417+0000][debug][metaspace ] Arena @0x0000ffff807a1cc0 (non-class sm): : born.
[2023-04-11T09:07:32.417+0000][debug][metaspace ] Arena @0x0000ffff807a1dd0 (class sm): : born.
[2023-04-11T09:07:32.417+0000][debug][metaspace ] CLMS @0x0000ffff807a1c80 : born (nonclass arena: 0x0000ffff807a1cc0, class arena: 0x0000ffff807a1dd0.
[2023-04-11T09:07:32.411+0000][debug][metaspace ] VsListNode @0x0000ffff80784ab0 base 0x0000000800c00000 : born (word_size 134217728).
[2023-04-11T09:07:32.417+0000][debug][metaspace ] VsListNode @0x0000ffff807a27b0 base 0x0000ffff52800000 : born (word_size 1048576).
这几行日志的意思是:
[0x0000000800000000-0x0000000800bde000-0x0000000800bde000)
,大小为 12443648 字节,共享基地址为 0x0000000800000000
,ArchiveRelocationMode
为关闭。这些信息我们不用太关心,主要和 CDS 特性相关(JEP 310: Application Class-Data Sharing 和 JEP 350: Dynamic CDS Archives),在以后的文章会详细分析。
[0x0000000800c00000-0x0000000840c00000)
,Reserved 内存大小为 1073741824 字节(1GB),默认压缩类空间最大大小就是 1GB。加载到压缩类空间的类的基地址为 0x0000000800000000
(),偏移量为 0,范围为 0x100000000
,这个前面也简单分析过。
Bootstrap ClassLoader
创建了两个 MetaspaceArena
,分别是前文分析的类元空间的 MetaspaceArena
和数据元空间的 MetaspaceArena
,放入对应的 ClassLoadMetaSpace
中。不要偷取他人的劳动成果,也不要浪费自己的时间和精力,让我们一起做一个有良知的写作者。
VirtualSpaceList
,并分别创建并放入各自的第一个 VirtualSpaceNode
接下来开始加载类,从元空间申请内存进行分配:
[2023-04-11T09:07:32.411+0000][debug][metaspace] ChkMgr @0x0000ffff807863d0 (class-space): requested chunk: pref_level: lv12, max_level: lv12, min committed size: 0.
[2023-04-11T09:07:32.411+0000][debug][metaspace] VsListNode @0x0000ffff80784ab0 base 0x0000000800c00000 : new root chunk @0x0000ffff807867f0, f, base 0x0000000800c00000, level lv00.
[2023-04-11T09:07:32.411+0000][debug][metaspace] ChkMgr @0x0000ffff807863d0 (class-space): allocated new root chunk.
[2023-04-11T09:07:32.411+0000][debug][metaspace] ChkMgr @0x0000ffff807863d0 (class-space): splitting chunk @0x0000ffff807867f0, f, base 0x0000000800c00000, level lv00 to lv12.
[2023-04-11T09:07:32.411+0000][debug][metaspace] ChkMgr @0x0000ffff807863d0 (class-space): handing out chunk @0x0000ffff807867f0, u, base 0x0000000800c00000, level lv12.
这几行日志的意思分别是:
MetaChunk
,优先考虑的与最大的 ChunkLevel
都是 12
,对应 1KB。本次申请发生在 ChunkManager @0x0000ffff807863d0
RootMetaChunk
,基址 0x0000000800c00000
RootMetaChunk
按照之前的算法拆分到 ChunkLevel
为 12
,结果是 MetaChunk @0x0000ffff807867f0
,将拆出来的其他 MetaChunk
放入 ChunkManager @0x0000ffff807863d0
的 FreeListVector
中jdk.MetaspaceSummary
元空间定时统计事件元空间定时统计事件 jdk.MetaspaceSummary
,包括以下属性:
Before GC
和 After GC
两种,分别是 GC 前和 GC 后的统计数据,可以根据 GC Identifier 对比 GC 前后的数据,看看 GC 之后元空间的使用情况.plagiarism和洗稿是恶意抄袭他人劳动成果的行为,是对劳动价值的漠视和践踏!_capacity_until_GC
MetaChunk
分配的时候 commit 所有内存)jdk.MetaspaceAllocationFailure
元空间分配失败事件前面提到过,如果普通分配失败,那么会触发 jdk.MetaspaceAllocationFailure
这个 JFR 事件,大家可以监控这个事件,去调整元空间大小减少由于元空间不足触发的 GC,这个事件包括以下属性:
Class
和 Metadata
Class
、ConstantPool
、Symbol
、Method
、Klass
、Module
、Package
、Other
这个事件也会采集堆栈信息,用来定位分配失败的源头是哪些类的加载导致的。
jdk.MetaspaceOOM
元空间 OOM 事件前面提到过,当元空间 OOM 的时候,就会产生这个事件,这个事件包括以下属性(和 jdk.MetaspaceAllocationFailure
事件一样):
Class
和 Metadata
Class
、ConstantPool
、Symbol
、Method
、Klass
、Module
、Package
、Other
与 jdk.MetaspaceAllocationFailure
事件一样,也会采集堆栈信息,用来定位 OOM 的原因。
jdk.MetaspaceGCThreshold
元空间 GC 阈值变化事件前面我们说过,元空间的 GC 阈值(_capacity_until_GC
)是动态调整的,这个事件就是用来记录元空间 GC 阈值变化的。这个事件包括以下属性:
_capacity_until_GC
有两个场景会修改: _capacity_until_GC
进行分配。对应的 Updater
是 expand_and_allocate
_capacity_until_GC
,如果有更新,就会生成这个事件,对应的 Updater
是 compute_new_size
jdk.MetaspaceChunkFreeListSummary
元空间 Chunk FreeList 统计事件这个事件在 Java 16 引入 JEP 387: Elastic Metaspace 弹性元空间的设计之后,里面的统计数据就都是 0 了,还没有实现,参考:https://bugs.openjdk.org/browse/JDK-8251342
,所以我们先不用关心。参考源码:https://github.com/openjdk/jdk/blob/jdk-21%2B17/src/hotspot/share/memory/metaspaceUtils.hpp
// (See JDK-8251342). Implement or Consolidate.
static MetaspaceChunkFreeListSummary chunk_free_list_summary(Metaspace::MetadataType mdtype) {
return MetaspaceChunkFreeListSummary(0,0,0,0,0,0,0,0);
}