概述

根据上一篇文章,将JVM升级到212版本,并追加设置了-Xmx和-Xms参数之后,生产环境的JVM内存一直维持在300-800M之间,高负载和低负载的实例,内存开销都在这个范围之内。所以从这两天的线上验证的现象来看是符合预期的,证实了之前的猜测是正确的(之前的结论参考:JVM的内存泄漏调查)。

详细分析

下面我将结合听云监控上的数据进行分析和论证。

下图是内存开销,可以看出内存开销在500M范围以下。

jvm memory cost!

下面是Eden区域的内存开销,可以看出eden区大小在250M之内。

jvm eden cost!

再来看看GC的运行的情况,这里看出来GC运行的频次明显比之前的(参考我之前的文章:JVM的内存泄漏调查) 要提高很多。

jvm gc cost!

综合如上的监控数据,可以得出如下的结论

  1. 因为升级了JVM到 212版本,并且设置了JVM的-Xmx参数,使得JVM的内存增长不再以物理机器的内存大小作为依据,而是以docker容器本身的内存大小作为增长的依据。

  2. GC的回收频次也比以前要提高很多,这说明当JVM自动扩容之后,如果没有达到GC的条件,就不会触发GC执行的,因此如果当前的JVM版本不能正确识别出docker的内存大小,就会导致JVM持续增长到物理机器内存的1/4,直到达到docker的内存限制极限,就会导致docker的内存溢出。

总结

当前问题中我们可以通过提高JVM版本使之兼容 docker,设置Xmx参数的方式来让JVM识别出正确的内存大小。