xms和xmx是否必须设置相等

最近申请了几台机器专门用来运行Kafka Streams应用,发现经常发生OOM导致应用挂掉,原因是启动的时候指定了-Xms2G -Xmx2G,所以16G内存的机器没启几个应用内存就被占满了,尽管这些程序只是空跑。查了一下一般都建议-Xms和-Xmx设置为相等,那么能不能设置为不一样呢?

先了解一下-Xms和-Xmx的含义

-Xms

初始堆的大小,也是堆大小的最小值,默认值是总共的物理内存/64(且小于1G),默认情况下,当堆中可用内存小于40%(这个值可以用-XX: MinHeapFreeRatio 调整,如-X:MinHeapFreeRatio=30)时,堆内存会开始增加,一直增加到-Xmx的大小

-Xmx


堆的最大值,默认值是总共的物理内存1/4,如果Xms和Xmx都不设置,则两者大小会相同,默认情况下,当堆中可用内存大于70%(这个值可以用-XX: MaxHeapFreeRatio 调整,如-X:MaxHeapFreeRatio=60)时,堆内存会开始减少,一直减小到-Xms的大小

可以通过以下命令查看系统默认的InitialHeapSize和MaxHeapSize:

1
java -XX:+PrintFlagsFinal -version | grep HeapSize


-Xms=-Xmx?

如果设定一个比较小的初始堆大小,并且程序需要的内存大于-Xms时,JVM将会分配更多的堆内存,且有可能需要移动一些objects和记账(book-keeping),这些动作都比较耗时,会使程序响应变慢,极端情况下甚至会导致OOM。假如程序在闲时和忙时的负载差别比较大,堆内存就会不停的伸缩。如果设置-Xms=-Xmx就不会有这样的问题

但是在测试环境或者开发环境中,Kafka并不会一直有数据(至少我的这个测试环境是这样,非UA),所以大部分时间Kafka Streams程序都是在空跑,所以堆内存会长期处于-Xms的状态。这种情况下设置-Xms=-Xmx是极大的浪费

结论

在生产环境,设置-Xms和-Xmx相等以保证程序稳定。在开发测试环境,设置一个比较小的-Xms,以支撑更多的测试程序运行