JVM MetaSpace垃圾回收流程咨询及触发Full GC的OOM场景问询
JVM Metaspace内存回收具体流程(Java 8)
结合你提供的JVM参数(Java 1.8.0_411,CMS GC),Metaspace的回收流程如下:
一、触发条件
当Metaspace满足以下任一条件时,会触发关联的Full GC来执行回收:
- Metaspace已使用内存达到
MetaspaceSize(你设置的256m):首次触发Full GC后,JVM会动态调整后续的触发阈值(除非指定-XX:+UseFixedMetaspaceSize)。 - Metaspace已使用内存占当前已分配Metaspace空间的比例达到
MaxMetaspaceFreeRatio(默认70%,你的场景触发条件):此时JVM会发起Full GC来回收无用类元数据,同时尝试优化Metaspace的空间占用。
二、具体回收流程
Full GC请求发起
当Metaspace触发回收阈值时,JVM会向GC调度器发起Full GC请求。由于你使用-XX:+UseConcMarkSweepGC,CMS收集器的Full GC会退化为Serial Old收集器执行(CMS本身仅负责堆的并发标记清除,Full GC阶段采用Serial Old做全局暂停式回收)。无用类元数据标记
Full GC期间,JVM会同时完成堆对象和Metaspace类元数据的可达性分析:- 对堆内所有对象做可达性扫描,标记存活对象。
- 遍历Metaspace中的类元数据,判断是否为无用类(需同时满足三个条件:该类的所有实例已被回收;加载该类的ClassLoader已被回收;
java.lang.Class对象无任何外部引用)。
类元数据与堆内存回收
- 清理Metaspace中标记为无用的类元数据:释放其占用的本地内存块,同时清理常量池、方法字节码、字段信息等关联数据。
- 回收堆内的无用对象(你的场景中堆使用率仅5%,这部分回收量极少)。
Metaspace空间调整
回收完成后,JVM会根据当前Metaspace的使用情况调整空间:- 若空闲比例超过
MinMetaspaceFreeRatio(默认40%),会主动缩小Metaspace的已分配空间,将多余本地内存释放给操作系统。 - 若回收后Metaspace仍不足,且未达到
MaxMetaspaceSize(你设置的512m),则会动态扩容Metaspace(扩容步长由JVM内部计算,默认逐步递增)。
- 若空闲比例超过
跨代引用处理
由于Metaspace的类元数据与堆对象存在双向引用(类元数据引用堆中的静态对象,堆对象引用Class实例),Full GC会处理这些跨代引用,确保可达性分析的准确性,避免内存泄漏。
三、对你场景的补充说明
你遇到的OOM前Full GC,核心是Metaspace使用率达70%触发的回收动作,堆回收只是附带操作。若这次Full GC无法回收足够的无用类元数据,后续类加载持续占用空间,最终会触及MaxMetaspaceSize=512m,触发OutOfMemoryError: Metaspace。
常见的排查方向:
- 是否存在大量动态生成类(如动态代理、字节码增强框架)。
- 是否有ClassLoader泄漏(如Web应用热部署时旧ClassLoader未被回收,导致关联类元数据无法释放)。
内容的提问来源于stack exchange,提问作者NoBug
相关产品推荐
相关产品推荐

