Java标志Xms和Xmx会覆盖标志XX:+UseCGroupMemoryLimitForHeap吗?

13

我正在Kubernetes上运行一个容器化的Java应用程序。

为了使jvm按照容器规格保留内存,必须设置标志-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap

如果同时设置这两个标志和Xms和Xmx标志,jvm的行为会是什么? 一个标志会覆盖另一个标志吗?

例如,如果我们在具有容器限制请求和响应4Gi的pod中使用 java -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -Xms -Xms2500M -Xmx2500M -jar myjar.jar,在具有128Gi内存的主机上,JVM将保留多少内存?

3个回答

12

-Xmx标志覆盖了-XX:+UseCGroupMemoryLimitForHeap标志。

-XX:+UseCGroupMemoryLimitForHeap标志让JVM检测容器中最大堆大小应该是多少。

-Xmx标志将最大堆大小设置为固定大小。

对于您的示例,JVM将保留2500M堆空间。还会有一些额外的内存使用用于非堆和jvm东西。

为了进一步调整容器中的内存使用情况,您可以使用-XX:MaxRAMFraction标志。 请参见此文章:https://blog.csanchez.org/2017/05/31/running-a-jvm-in-a-container-without-getting-killed/


你可以使用“-XshowSettings:vm”命令在Java中进行测试并运行容器,以查看其设置。 - Thiago

4

这样来想一下,在添加UseCGroupMemoryLimitForHeap之前,您可以指定一个比您的pod拥有的内存更大的Xmx值(它只会查看主机内存,而不是pod本身),最终被杀掉。如果没有指定,默认情况下为内存的1/4。这是因为堆的计算方式如下:

heap = memory / MaxRAMFraction

并且运行:

java -XX:+PrintFlagsFinal | grep MaxRAMFraction

如果查看 MaxRAMFraction = 4,可以了解到多少堆内存来自于pod本身。现在添加了UseCGroupMemoryLimitForHeap,您可以告知从pod本身将使用多少堆内存, 默认情况下仍然是1/4;但您当然可以通过MaxRAMFraction进行调整。

如果指定了两个参数,Xms 将获胜。这很合理(因为UseCGroupMemoryLimitForHeapXmx更具体),并且这正是我的实验所证明的。无论它们的指定顺序如何,Xmx始终获胜。


1
MaxRAMFraction已被弃用 https://bugs.openjdk.java.net/browse/JDK-8187125 - 袁文涛
@袁文涛 是的...我应该编辑这个。在撰写时它还没有被弃用。 - Eugene

2
如果您正在运行Java 8更新191或更高版本,或者Java 10、11、12、13等版本,则不能使用UseCGroupMemoryLimitForHeap选项。相反,您应该使用默认激活的UseContainerSupport选项。
然后,您可以使用以下选项控制内存:InitialRAMPercentageMaxRAMPercentageMinRAMPercentage
请参见https://merikan.com/2019/04/jvm-in-a-container/

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接