Do java flags Xms and Xmx overwrite flag XX:+UseCGroupMemoryLimitForHeap?
Asked Answered
T

3

14

I'm running a containerized java application in Kubernetes.

In order to make the jvm reserve memory according to the container specifications, the flags -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap must be set.

If both those flags are set along with Xms and Xmx flags, what would the behavior of the jvm be? Do one flag overwrite the other?

For example, if we had java -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -Xms -Xms2500M -Xmx2500M -jar myjar.jar in a pod with container limits 4Gi for requests and 4Gi for responses, in a host machine that has 128Gi memory, how much memory would the JVM reserve?

Trincomalee answered 28/9, 2018 at 12:11 Comment(0)
I
12

The -Xmx flag overwrites the -XX:+UseCGroupMemoryLimitForHeap flag.

The flag -XX:+UseCGroupMemoryLimitForHeap lets the JVM detect what the max heap size in a container should be.

The -Xmx flag set the max heap size to a fixed size.

To answer your example, the JVM would reserve 2500M heap space. There will be some additional memory usage for non-heap and jvm stuff.

To further tune your memory usage in a container you could use the -XX:MaxRAMFraction flag. See this article: https://blog.csanchez.org/2017/05/31/running-a-jvm-in-a-container-without-getting-killed/

Innocuous answered 28/9, 2018 at 12:55 Comment(1)
You can make a test and run the container using -XshowSettings:vm for the java and get see its settingsBuckskin
M
4

Think about it this way, before that UseCGroupMemoryLimitForHeap was added, you could specify Xmx with a value larger than what your pod had (it would look only on the host memory, not the pod itself), eventually being killed. By default that was 1/4 of the memory if not specified. This happens because heap is calculated like:

heap = memory / MaxRAMFraction

And running:

java -XX:+PrintFlagsFinal | grep MaxRAMFraction

would reveal that MaxRAMFraction = 4.

Now that UseCGroupMemoryLimitForHeap was added, you can tell how much heap from the pod itself will be taken. By default, that is still 1/4; but you can adjust that via MaxRAMFraction, of course.

If you specify both arguments, Xms wins. always. And 1) this is pretty logic (as UseCGroupMemoryLimitForHeap is more specific than Xmx) 2) this is exactly proven by my experiments just now. No matter the order in which they are specified, Xmx always wins.

Murial answered 28/9, 2018 at 13:52 Comment(2)
MaxRAMFraction deprecated bugs.openjdk.java.net/browse/JDK-8187125Bousquet
@袁文涛 yeah... I should edit this one. At the time of the writing it was not deprecated.Murial
P
2

If you are running Java 8 update 191 or later, or Java 10, 11,12, 13 etc. you must NOT use the UseCGroupMemoryLimitForHeap option. Instead you should use the UseContainerSupport that is activated by default.

You can then control the memory with the following options, InitialRAMPercentage, MaxRAMPercentage and MinRAMPercentage.

See https://merikan.com/2019/04/jvm-in-a-container/

Phatic answered 23/3, 2022 at 14:40 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.