metaSpace引起full gc排查过程

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

一、查看内存使用率

命令:jstat -gcutil PID ,这里的PID是Java进程ID

metaSpace引起full gc排查过程

可以看到老年代使用率只有1.96%,但是MetaSpace区域使用率是96.13%,初步怀疑是metaSpace区域设置太小。

 

二、查看gc日志(JVM参数里可以配置打印gc信息)

metaSpace引起full gc排查过程

项目采用的CMS垃圾回收期来回收老年代,CMS垃圾回收期在fullgc的步骤可以分为:

初始标记(STW)->并发标记->并发预清理->重标记(STW)-> 并发清理->重置,对应到截图里是一次完整的fullGC的过程,下面分析日志:

标记1的位置是[ParNew: 218582K->15126K(235968K), 0.0166181 secs],这句意思是新生代在垃圾回收前占用218582K,回收后占用15126K,总容量235968K,耗时0.0166181,这是一次正常的minor gc

标记2的信息很可疑,218582K->15126K(1022400K),这句意思是整个堆在gc前占用218582K,回收后15126K,总大小为1022400K,也就是说在使用量20%左右时就出现了fullgc,标记3的地方也说明整个堆的使用量很低。

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

 

已知的触发fullgc的条件有:

老年代空间不足 – 排除

永久带空间不足,也就是jdk8里metaSpace区域

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参数的默认值可以通过java -XX:+PrintFlagsFinal -version |grep JVMParamName获取,例如:java -XX:+PrintFlagsFinal -version |grep MetaspaceSize

metaSpace引起full gc排查过程metaSpace引起full gc排查过程 33333333 发布了19 篇原创文章 · 获赞 3 · 访问量 9602 私信 关注
上一篇:虚拟机参数


下一篇:Robotframework(2):创建RF第一条可执行的用例