记一次JDK8版本下的SpringBoot工程Metaspace溢出问题处理

目录

背景

分析

JVM启动项

代码逻辑优化

处理结果

深层分析

参考资料


背景

某次新功能迭代,经部署后发现Pod出现OOM,报错日志为:

java.lang.OutOfMemoryError: Metaspace

分析

JVM启动项

因为是在容器部署的,首先检查了下startup.sh启动脚本,发现设置JVM参数的时候显式的设置了metaspace大小为Pod总内容大小的1/20。算下给Pod分配的总内存是4G,那么mataspace的总大小是200M,很快就溢出了。

limit_in_bytes=$(cat /sys/fs/cgroup/memory/memory.limit_in_bytes)
if [ "$limit_in_bytes" -ne "9223372036854771712" -a "$limit_in_bytes" -ne "9223372036854775807" ]; then
  limit_in_megabytes=$(expr $limit_in_bytes \/ 1048576)
  heap_size=$(expr $limit_in_megabytes \* 4 \/ 7)
  mate_size=$(expr $limit_in_megabytes \* 1 \/ 20)
  export JAVA_OPTS="-Xmx${heap_size}m -Xms${heap_size}m $JAVA_OPTS -XX:MaxMetaspaceSize=${mate_size}m -XX:MaxDirectMemorySize=${mate_size}m -XX:CompressedClassSpaceSize=${mate_size}m -XX:-UseAdaptiveSizePolicy -XX:SurvivorRatio=8 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/envuser/logs -XX:ErrorFile=/home/logs/hs_err_%p.log"
  echo JAVA_OPTS=$JAVA_OPTS
fi

经查找相关资料发现metaspace如果不设置,默认是可以动态调整的,所以这里做的第一个修改就是将JVM的参数更改掉

if [ "$limit_in_bytes" -ne "9223372036854771712" -a "$limit_in_bytes" -ne "9223372036854775807" ]
then
    limit_in_megabytes=$(expr $limit_in_bytes \/ 1048576)
    heap_size=$(expr $limit_in_megabytes \* 3 \/ 4)
    export JAVA_OPTS="-Xmx${heap_size}m $JAVA_OPTS"
    echo JAVA_OPTS=$JAVA_OPTS
fi

代码逻辑优化

因为这个版本引入了一些文件和二进制流处理的逻辑,另外一个很重要的原因就是排查代码,发现代码中有些操作了InputStream和ReadBuffer后没有关闭的情况,也将这块逻辑进行了调整优化。

处理结果

经过前两部初步处理后没有明显观察到metaspace溢出的情况了。

深层分析

待进一步补充

参考资料

JVM 问题排查和性能优化常用的 JDK 工具 - 风的姿态 - 博客园

java高分局之jstat命令使用_褚金辉的博客-CSDN博客_jstat mc mu

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值