某天早上,毛老师在群里问「cat 上怎么看 gc」。
看到有 GC 的问题,立马做出小鸡搓手状,之后毛老师发来一张图。
图片展示了老年代内存占用情况:第一个大陡坡是应用发布,老年代内存占比下降,很正常。第二个小陡坡,老年代内存占用突然下降,应该是发生了老年代 GC。但奇怪的是,此时老年代内存占用并不高,发生 GC 并不是正常现象,于是,毛老师查看了 GC log。
从 GC log 中可以看出,老年代发生了一次 CMS GC,但此时老年代内存使用占比 = 234011K / 2621440k ≈ 9%。
而 CMS 触发的条件是:老年代内存使用占比达到CMSInitiatingOccupancyFraction
,默认为 92%,毛老师设置的是 75%。
1-XX:CMSInitiatingOccupancyFraction = 75
于是排除老年代占用过高的可能,接着分析内存状况。
毛老师发现在老年代发生 GC 时,Metaspace 的内存占用也一起下降。于是怀疑是 Metaspace 占用达到了设置的参数 MetaspaceSize,发生了 GC。查看 JVM 参数设置,MetaspaceSize 参数被设置为128m。
1-XX:MetaspaceSize = 128m -XX:MaxMetaspaceSize = 256m
问题的原因被集中在 Metaspace 上。毛老师查看另外一个监控工具,发生小陡坡的纵坐标的确接近 128m。此时,引发出另一个问题:
Metaspace 发生 GC,为何会引起老年代 GC。
于是,想到之前看过 文章 《JVM参数MetaspaceSize的误解》。
其中有几个关键点:
- Metaspace 在空间不足时,会进行扩容,并逐渐达到设置的 MetaspaceSize。
- Metaspace 扩容到 -XX:MetaspaceSize 参数指定的量,就会发生 FGC。
- 如果配置了 -XX:MetaspaceSize,那么触发 FGC 的阈值就是配置的值。<