maxmetaspacesize是元空间硬性内存上限,超限且gc无法释放时抛出outofmemoryerror: metaspace导致崩溃;必须与metaspacesize设为相同值(如256m)协同使用,否则默认20.8mb仍会触发频繁full gc。

MaxMetaspaceSize 是元空间能使用的最大本地内存上限,不是建议值,而是硬性边界。一旦元空间已用容量超过这个值,且 GC 无法释放足够空间,JVM 就会抛出 java.lang.OutOfMemoryError: Metaspace,应用直接崩溃。它不控制初始分配,也不影响启动时的行为,只起“兜底”作用。
为什么必须设 MaxMetaspaceSize?
Java 8 取消永久代后,元空间默认无上限(-1),完全依赖系统物理内存。这在以下场景极易失控:
- 微服务频繁重启或热部署,类加载器未卸载,元数据持续累积
- 使用大量反射、动态代理(如 Spring AOP、MyBatis Mapper)、字节码增强(AspectJ、Byte Buddy)
- 插件化架构或运行时加载第三方 SDK(如 Android 插件、报表引擎)
- 容器环境(如 Docker)中未限制内存,JVM 可能吃光宿主机内存
和 MetaspaceSize 的关系不能搞错
只设 -XX:MaxMetaspaceSize=256m 而不设 -XX:MetaspaceSize,等于白设——JVM 仍按默认约 20.8 MB 启动,很快触发首次 Metaspace GC,反复扩容收缩,引发大量 Full GC。
真正有效的做法是:两者设为相同值,例如:
-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m- 中大型服务可设为
512m或768m;含大量运行时生成类的场景可到1g - 避免设为
2g以上且长期低负载,会浪费宝贵本地内存
如何确认它生效了?
启动后别只看配置文件,要查运行时实际值:
-
jinfo -flag MetaspaceSize <pid></pid>和jinfo -flag MaxMetaspaceSize <pid></pid>—— 看是否读取正确 -
jstat -gc <pid></pid>—— 关注MC(Metaspace capacity)是否接近你设的上限值 - 开启 GC 日志(
-Xloggc:gc.log -XX:+PrintGCDetails),搜索Metadata GC Threshold,确认 FGC 是否明显减少
额外提醒:它管不了压缩类空间
MaxMetaspaceSize 不限制 Compressed Class Space(压缩类指针空间)。如果出现 OutOfMemoryError: Compressed class space,需单独加参数:-XX:CompressedClassSpaceSize=256m(默认约 1GB,但可调小)。











