Jar工程运行java.lang.OutOfMemoryError: Metaspace

错误的原因大概率是加载到内存中的 class 占用的内存超过了 Metaspace 的限制

Metaspace 的使用机制

  1. JVM 加载类时,会进行以下操作最终将类加载进内存
    • 通过一个类的全限定名来获取其定义的二进制字节流
    • 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构,也就是存储在 Metaspace 中
    • 在Java堆中生成一个代表这个类的 java.lang.Class对象,作为对方法区中这些数据的访问入口
  2. 当 Metaspace 空间不足的时候,会触发 Full GC 卸载一些无用的类以便回收内存,类的卸载条件是很苛刻的,即便进行了
    Full GC,JVM 也无法回收到足够的内存以存储新加载的类,最终导致其占有的内存超过限制,只能报出 OOM 错误
  3. Metaspace 空间不足触发 Full GC 这个点只要多执行几次 jstat -gcutil pid 命令,观察 Full GC 的次数变化就能看出来,需注意 Full GC 非常影响程序效率,应该避免

解决方式

Metaspace 空间不足,那么增大 Metaspace 的空间就可以了,这种方式简单粗暴,但是高效
Metaspace 空间不足大概率是因为加载的类太多,而受限于苛刻的类卸载条件无法将其回收掉,那么最好的解决方式就是不加载那些不需要的类。基于这个思路,检查服务是否加载了过多的类,将其找出来,去除掉多余的加载项。这种方式治标治本,但是比较耗时

配置

  • -XX:MaxMetaspaceSize=256m(调整大小)
  • 直接去掉 -XX:MaxMetaspaceSize 启动参数,不限制 Metaspace内存的大小。这种方式需要注意,假若机器物理内存不足,有可能会引起内存交换(swapping),严重拖累系统性能,还可能造成 native 内存分配失败等问题

总结:占用内存过多通常有以下两种原因

  • 引用的 jar 包加载了很多 class
    这种情况需要排查服务中引用的比较大的 jar 包,去除掉多余的加载项,对于那些不能去掉的,按照最小粒度去加载
  • 动态生成类过多
    Java 的许多框架会大量使用动态代理等技术动态生成类,使用这样的方式创建对象可能会有大量动态类产生,元空间消耗会增加,这种情况似乎没有好的解决方法

Metaspace 参数汇总

  1. -XX:MetaspaceSize=N
  • 初始化的 Metaspace 大小,该值越大触发 Metaspace 区域 GC 的时机就越晚。
  • 随着GC的到来,JVM 会根据实际情况调控 Metaspace 的大小,可能增加上限也可能降低
  1. -XX:MaxMetaspaceSize=N

    限制 Metaspace 内存的最大值,
    防止因为某些情况导致 Metaspace 无限使用本地内存,影响到其他程序
    
  2. -XX:MinMetaspaceFreeRatio=N

    当进行过 Metaspace 区域 GC 之后,JVM 会计算当前 Metaspace 的空闲空间比,
        如果空闲比小于这个参数,那么 JVM 将增大 Metaspace 的内存大小。
    
    该参数的默认值为40,也就是40%。
    设置这个参数可以控制 Metaspace 的增长的速度
        太小的值会导致 Metaspace 增长缓慢,Metaspace 的使用逐渐趋于饱和,可能会影响之后类的加载。
        而太大的值会导致 Metaspace 增长过快,浪费内存
    
  3. XX:MaxMetasaceFreeRatio=N

    当进行过 Metaspace 区域的GC之后, 会计算当前 Metaspace 的空闲空间比,
    如果空闲比大于这个参数,那么虚拟机会释放 Metaspace 的部分空间。
    该参数的默认值为70,也就是70%
    
  4. -XX:MaxMetaspaceExpansion=N

    Metaspace 增长时的最大幅度,参数的默认值为5452592B(大约为5MB)
    
  5. -XX:MinMetaspaceExpansion=N

    Metaspace 增长时的最小幅度,该参数的默认值为340784B(大约为330KB)
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值