JVM——12.定位 Metaspace OOM

1. Metaspace区是怎么发生OOM的

在jvm中,用来控制Metaspace区域内存大小的参数一般有两个:

  • -XX:MetaspaceSize:Metaspace初始大小;
  • -XX:MaxMetaspaceSize:Metaspace最大大小;

也就是说,对应一个jvm来说,Metaspace区域的大小是固定的,比如设置为:-XX:MetaspaceSize=512M -XX:MaxMetaspaceSize=512M

那如果在应用执行的时候,不断的加载类,使得Metaspace区域被很多类放满了,会发生什么情况呢?

我们前面说过,在发生 Full GC的时候,会带着一起回收Metaspace区域的垃圾对象的;所以一旦Metaspace区域满了,此时它也会触发 Full GC,然后尝试回收自己里面的垃圾对象。

这里就有一个问题,Metaspace区域中的类(klass,class文件在jvm里的运行时数据结构),怎么判断它是否为垃圾对象呢?在这里它的判断条件要比Java堆中的实例对象严格很多:

  • 该类的所有实例对象都已经被回收(Java堆中不存在它的任何实例);
  • 加载该类的ClassLoader都已经被回收;
  • 该类对应的 java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法;

所以当Metaspace满了的时候,就算执行了Full GC,也未必能够回收掉很多它里面的类;当不能回收很多类的时候,jvm还在继续加载类到Metaspace中,那它也没有地方来存这些类了,也就只有发生OOM了。

2. 什么情况会发生Metaspace的OOM

其实对于日常的项目运行情况来说,Metaspace区域是很少发生OOM的;如果发生了OOM,一般都是以下两个原因:

  • 在上线系统的时候,使用默认参数,没有指定Metaspace区域的大小,导致Metaspace区域只有默认的20M左右;这对于稍微大一点的系统,本身自己就有很多类,还有依赖的一些第三方框架等也有很多类,20M左右的Metaspace很容易就被填满了;
    • 这里再介绍一个查看jvm中默认参数大小的命令java -XX:+PrintFlagsFinal -version | grep MetaspaceSize
    • 应对这种情况,正常的应用部署上线都需要设置Metaspace大小;小一点的应用设置为 256M,大一点的应用设置为512M,一般都够用了;
  • 在系统代码中用到了一些cglib等技术动态的生成了一些类,如果代码中没有控制好,导致生成的类过多,很容易就把Metaspace填满;
    • 应对这种情况,如果代码中有需要动态生成类,就需要好好检查代码了,注意生成的数量和回收;如果遇到了这种oom也需要再次回来检查代码;
  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值