记一次JDK8的Metaspace区域的调优过程,及MetaspaceSize参数的误解

JDK8用metaSpace区域来代替了以前的永久区,这个区域主要存放被加载的class信息,我手上一个项目每次启动时候都会伴随一次fullgc,排查思路是:

一、查看内存使用率
命令:jstat -gcutil PID ,这里的PID是Java进程ID
在这里插入图片描述
可以看到老年代使用率只有1.96%,但是MetaSpace区域使用率是96.13%,初步怀疑是metaSpace区域设置太小。

二、查看gc日志(JVM参数里可以配置打印gc信息)
在这里插入图片描述
项目采用的CMS垃圾回收期来回收老年代,CMS垃圾回收期在fullgc的步骤可以分为:
初始标记(STW)->并发标记->并发预清理->重标记(STW)-> 并发清理->重置,对应到截图里是一次完整的fullGC的过程,下面分析日志:

  1. 标记1的位置是[ParNew: 218582K->15126K(235968K), 0.0166181 secs],这句意思是新生代在垃圾回收前占用218582K,回收后占用15126K,总容量235968K,耗时0.0166181,这是一次正常的minor gc
  2. 标记2的信息很可疑,218582K->15126K(1022400K),这句意思是整个堆在gc前占用218582K,回收后15126K,总大小为1022400K,也就是说在使用量20%左右时就出现了fullgc,标记3的地方也说明整个堆的使用量很低。

从gc日志上得到的信息也差不多,和堆没关系。

已知的触发fullgc的条件有:

  1. 老年代空间不足 – 排除
  2. 永久带空间不足,也就是jdk8里metaSpace区域
  3. CMS在gc时出现promotion failed和concurrent mode failure

promotion failed是指新生代对象晋升到老年代时,老年代空间不足时触发fullgc,这个可以排除
concurrent mode failure 是指CMS在进行老年代垃圾回收时,由于CMS在gc时为了减少STW停顿时间,采用用户线程和垃圾回收线程并行执行的方式,所以此时用户线程还是会产生内存对象,这些对象就是浮动对象,如果此时有浮动对象晋升到老年代,而老年代空间不足时,就会触发concurrent mode failure,导致JVM不得不停止用户线程来进行fullgc,这时候就会STW,而我这边的老年代空间充足,可以排除。

这样基本可以确定是metaSpace问题,于是网上查了下参数,在JVM启动参数里加上-XX:MetaspaceSize=64m -XX:MaxMetaspaceSize=512m,想到最小64M,最大512M,这下总可以了,结果启动项目后还是会产生fullGc…,然后再看了下MetaspaceSize参数含义:

那么-XX:MetaspaceSize=256m的含义到底是什么呢?其实,这个JVM参数是指Metaspace扩容时触发FullGC的初始化阈值,也是最小的阈值。这里有几个要点需要明确:

如果没有配置-XX:MetaspaceSize,那么触发FGC的阈值是21807104(约20.8m),可以通过jinfo -flag MetaspaceSize pid得到这个值;
如果配置了-XX:MetaspaceSize,那么触发FGC的阈值就是配置的值;
Metaspace由于使用不断扩容到-XX:MetaspaceSize参数指定的量,就会发生FGC;且之后每次Metaspace扩容都可能会发生FGC(至于什么时候会,比较复杂,跟几个参数有关);
如果Old区配置CMS垃圾回收,那么扩容引起的FGC也会使用CMS算法进行回收;
如果MaxMetaspaceSize设置太小,可能会导致频繁FullGC,甚至OOM;


任何一个JVM参数的默认值可以通过java -XX:+PrintFlagsFinal -version |grep JVMParamName获取,例如:java -XX:+PrintFlagsFinal -version |grep MetaspaceSize

作者:阿飞的博客
链接:https://www.jianshu.com/p/b448c21d2e71
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。   

最后将MetaspaceSize参数调大就解决问题了。

  • 1
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在进行 JDK 1.8 的 JVM 参数调优时,可以考虑以下几个方面: 1. 堆内存设置: - 调整初始堆大小和最大堆大小,使用 `-Xms` 和 `-Xmx` 参数来设置。根据应用的负载情况和服务器的可用内存,合理分配堆内存大小。 2. 垃圾回收器选择: - JDK 1.8 默认使用的是并行垃圾回收器(Parallel GC)。如果应用有较高的并发需求,可以考虑使用并发标清除垃圾回收器(CMS GC)或 G1 垃圾回收器(G1 GC)。 3. 并行度设置: - 根据服务器的 CPU 核心数量和应用负载情况,调整并行垃圾回收的线程数。使用 `-XX:ParallelGCThreads` 参数来设置,并行垃圾回收线程的数量。 4. 元空间(Metaspace)设置: - 元空间是 JDK 1.8 中替代永久代的内存区域。可以使用 `-XX:MaxMetaspaceSize` 参数来设置元空间的最大大小。 5. 垃圾回收相关参数: - 根据应用的特点和性能需求,调整垃圾回收相关参数。例如,可以使用 `-XX:MaxGCPauseMillis` 来设置最大垃圾回收停顿时间,以平衡吞吐量和停顿时间。 6. 监控与调优工具: - 使用 JDK 自带的工具,如 jstat、jmap、jstack 等,来监控应用的内存、垃圾回收情况和线程状态。根据监控结果,进行针对性的调优。 注意,JVM 参数调优需要根据具体应用的特点和实际情况进行实验和测试,以获得最佳性能和稳定性。建议在进行参数调优前,先了解应用的负载情况和性能瓶颈,并备份原有的参数配置,以便在调优过程中出现问题时可以回滚。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值