metaspace扩容后能否回收是关键,需关注gc日志中“metadata gc threshold”或“class unloading”标记,结合used→used(capacity)变化、classes unloaded数量及classloader增长情况判断类卸载是否生效。

直接看 GC 日志里带 Metaspace 字样的行,重点不是“有没有扩容”,而是“扩完收不收得回来”。
识别 Metaspace 扩容触发的 GC 记录
日志中出现以下任一标记,说明 Metaspace 触发了 GC:
-
[GC (Metadata GC Threshold)]:Metaspace 使用量突破初始阈值(由
-XX:MetaspaceSize决定),触发一次 Young GC,并尝试回收元数据 -
[Full GC (Metadata GC Threshold)]:Metaspace 已达上限(
-XX:MaxMetaspaceSize),Young GC 无法释放足够空间,被迫执行 Full GC - [GC (Class Unloading)]:ClassLoader 被回收,关联类元数据批量释放——这是健康信号,说明卸载机制生效
关键字段怎么看:used→used(capacity)
例如这一行:[Metaspace: 10240K->10240K (1056768K)]
Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。 当用户需要:(1) 编写或审查Java代码 (2) 检查命名/代码规范 (3) 处理异常和日志 (4) 编写单元测试 (5) 安全编码 (6) 数据库设...
- 箭头前是 GC 前已用空间(used),箭头后是 GC 后已用空间(used)
- 括号内是当前总容量(capacity),它会随扩容增长;若 capacity 不涨但 used 持续逼近它,说明已达
MaxMetaspaceSize上限 - 如果
10240K->10240K这种“几乎不变”的模式反复出现,代表类卸载失败,元数据堆着没清掉
搭配 -XX:+PrintClassLoaderStatistics 看卸载是否真实发生
仅靠 Metaspace 数字不够,必须确认类是否被真正卸载:
- 日志中找
Classes unloaded:行——长期为0或个位数,说明卸载基本没发生 - 关注
ClassLoader数量是否持续上升,尤其非AppClassLoader的自定义加载器(如DynamicClassLoader、LaunchedURLClassLoader) - 若类数量(
Loaded classes)涨得快、卸得少,再结合类名含$$EnhancerByCGLIB、Proxy$、GeneratedMethodAccessor,基本锁定动态代理或反射膨胀问题
注意 GC 类型与类卸载能力的匹配关系
不是所有 GC 都能卸载类,参数配错等于白开:
-
G1:JDK 8u40+ 支持类卸载,需同时启用-XX:+UseG1GC和-XX:+ClassUnloading(旧版可能还需-XX:+UnlockExperimentalVMOptions) -
CMS:需显式加-XX:+CMSClassUnloadingEnabled -
Parallel GC(-XX:+UseParallelGC):默认完全不卸载类,加了卸载参数也无效 - 用
jstat -gc <pid></pid>查看 GC 列,确认实际使用的收集器类型
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










