如何解决java.lang.OutOfMemoryError: Metaspace_元空间溢出调优与排查

风静君_3959

风静君_3959

2026-03-21

307人浏览

原创

metaspace溢出时jvm直接崩溃而非gc,因其使用本地内存,gc无法管理;超-xx:maxmetaspacesize即抛outofmemoryerror并终止进程。

如何解决java.lang.outofmemoryerror: metaspace_元空间溢出调优与排查

Metaspace 溢出时 JVM 为什么会直接崩溃而不是 GC?

因为 Metaspace 不在堆内,它用的是本地内存(Native Memory),GC 只管堆,对 Metaspace 无能为力。一旦加载的类元数据(比如动态生成的类、大量第三方库、反复热部署)超过 -XX:MaxMetaspaceSize 限制,JVM 就会抛 java.lang.OutOfMemoryError: Metaspace 并终止线程或整个进程。

常见诱因包括:Spring Boot 多模块热重启、使用 CGLIB/ByteBuddy 动态代理过多、Groovy/Scala 脚本频繁编译、Tomcat 部署多个 WAR 包未清理旧版本。

  • 默认情况下 -XX:MaxMetaspaceSize 是无上限的(只受系统内存约束),但生产环境必须显式设置,否则可能把物理内存耗尽
  • -XX:MetaspaceSize 是触发首次 Metaspace GC 的阈值(不是初始大小),设太小会导致早期频繁 GC;设太大则可能延迟问题暴露
  • JDK 8+ 才用 Metaspace,JDK 7 及以前是永久代(PermGen),错误信息是 java.lang.OutOfMemoryError: PermGen space,调参方式完全不同

怎么快速确认是不是 Metaspace 真的满了?

别猜,用 JDK 自带工具看实时占用。启动时加 -XX:+PrintGCDetails -XX:+PrintGCTimeStamps,GC 日志里会出现类似 Metaspace used 245760K, capacity 246144K, committed 246784K, reserved 1114112K 的行——重点盯 used 和 capacity 是否持续逼近甚至超过 MaxMetaspaceSize。

更准的方式是运行时检查:

  • 用 jstat -gc <pid></pid> 查看 MU(Metaspace Used)和 MC(Metaspace Capacity)列
  • 用 jcmd <pid> VM.native_memory summary</pid> 看 native 内存中 Class 区域是否异常高
  • 如果应用支持 JMX,连 JConsole 或 VisualVM,直接看 java.lang:type=MemoryPool,name=Metaspace 的 Usage.used 值

调参顺序和关键参数怎么设才不翻车?

先观察再调整,别一上来就拍脑袋设 512m。典型安全起手式:

  • 先加 -XX:MaxMetaspaceSize=256m(中小应用)或 512m(Spring Cloud 微服务),强制暴露问题
  • 配合 -XX:MetaspaceSize=128m,避免刚启动就触发 GC,又不至于太晚才回收
  • 加上 -XX:+TraceClassLoading 和 -XX:+TraceClassUnloading(仅调试期),确认哪些类在疯涨、有没有卸载失败
  • 绝对不要设 -XX:MinMetaspaceFreeRatio 或 -XX:MaxMetaspaceFreeRatio 来“优化”,它们对 Metaspace GC 行为影响极小,还容易干扰判断

注意:-XX:MaxMetaspaceSize 设得比系统剩余内存还大,等于没设;设得太小(比如 64m)会导致 Spring Boot 启动失败,报错里常带 Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass。

代码和框架层面真正该砍掉什么?

参数只是止痛药,根因往往在代码或依赖。重点关注三类“元空间黑洞”:

  • Spring Boot DevTools 热加载 + Lombok + MapStruct 混用,每次保存都生成新类,老类卸载不干净 → 关掉 DevTools 或改用 spring-boot-devtools 的 restart.enabled=false
  • MyBatis-Plus 的 AutoGenerator 在测试里反复执行,每跑一次就生成一批 Mapper 类 → 改成单例缓存,或只在构建期生成
  • Logback 使用 %replace 或自定义 Converter 且内部 new ClassLoader → 检查日志配置,避免在 converter 中动态加载类

一个容易被忽略的点:某些国产中间件 SDK(比如部分金融信创组件)会在运行时反射生成大量匿名内部类,且不释放,这类问题光调参没用,得联系厂商或换 SDK。

Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南

相关文章

java速学教程(入门到精通)
java速学教程(入门到精通)

java怎么学习?java怎么入门?java在哪学?java怎么学才快?不用担心,这里为大家提供了java速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

java

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
java
java

Java是一个通用术语,用于表示Java软件及其组件,包括“Java运行时环境 (JRE)”、“Java虚拟机 (JVM)”以及“插件”。php中文网还为大家带了Java相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

2023.06.15

10757

6

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

2023.07.05

7882

9

java自学难吗
java自学难吗

Java自学并不难。Java语言相对于其他一些编程语言而言,有着较为简洁和易读的语法,本专题为大家提供java自学难吗相关的文章,大家可以免费体验。

2023.07.31

6852

8

java配置jdk环境变量
java配置jdk环境变量

Java是一种广泛使用的高级编程语言,用于开发各种类型的应用程序。为了能够在计算机上正确运行和编译Java代码,需要正确配置Java Development Kit(JDK)环境变量。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.01

1164

3

java保留两位小数
java保留两位小数

Java是一种广泛应用于编程领域的高级编程语言。在Java中,保留两位小数是指在进行数值计算或输出时,限制小数部分只有两位有效数字,并将多余的位数进行四舍五入或截取。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.02

948

3

java基本数据类型
java基本数据类型

java基本数据类型有:1、byte;2、short;3、int;4、long;5、float;6、double;7、char;8、boolean。本专题为大家提供java基本数据类型的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

1396

5

java有什么用
java有什么用

java可以开发应用程序、移动应用、Web应用、企业级应用、嵌入式系统等方面。本专题为大家提供java有什么用的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

2829

5

java在线网站
java在线网站

Java在线网站是指提供Java编程学习、实践和交流平台的网络服务。近年来,随着Java语言在软件开发领域的广泛应用,越来越多的人对Java编程感兴趣,并希望能够通过在线网站来学习和提高自己的Java编程技能。php中文网给大家带来了相关的视频、教程以及文章,欢迎大家前来学习阅读和下载。

2023.08.03

20131

3

配置java环境变量
配置java环境变量

配置Java环境变量是为了让操作系统能够识别和使用Java的相关命令和功能。本专题为大家提供配置java环境变量相关文章,帮助大家解决问题。

2023.08.03

1255

8

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
dev.java 官方:Learn Java
dev.java 官方:Learn Java

共0课时 | 0人学习

Java JDBC数据库连接官方教程
Java JDBC数据库连接官方教程

共0课时 | 0人学习