4

I have a Java application, based on Java8 OpenJDK. It's running in a docker container which has a limit of 20GB.

The -Xms and -Xmx settings of tomcat is set as follows:

-Xms = 60% of the container memory (as dictated by the cgroup) - so 12GB -Xmx = 80% of the container memory (as dictated by the cgroup) - so 16GB

This leaves 4GB free on the container, which is usually fine, but sometimes under load I see the docker container exited (and java process killed) with OOM due to the fact container memory usage has exceeded 20GB.

I know that the -Xmx settings is for the heap, and not the whole Java process and JVM, therefore would expect that the 4GB 'headroom' on the container is enough, but it appears not.

I know all use cases are wildly different, but my question is whether, in general terms, setting the -Xmx setting is too high for a container whose memory limit is 20GB.

I was toying with the idea of using the MaxRAM setting, which again, I know only dictates the heap memory, but I'm unsure whether that would have any impact in positive terms?

Is it generally the case that you use either MaxRAM or -Xmx, or is there any benefit to setting both?

If I were to use MaxRAM instead of -Xmx, how would java allocate memory to the heap? Is there a simple algorithm for this, for example, 50% of the MaxRAM setting? Will java manage memory any more efficiently doing it that way?

Molenpad
  • 833
  • 2
  • 14
  • 34
  • 1
    The MaxHeapSize is calculated as ContainerSize * MaxRAMPercentage. By default the MaxRAMPercentage is 25 (25% from the max container size). I always set -XX:MaxRAMPercentage=70.0 (75 or 80 is to much and I got OOM after a while) and never set -Xmx. Having this settings I didn't have any OOM – Octavian R. Dec 02 '20 at 19:48
  • @OctavianR. Not all JDK 8 versions use that logic – OneCricketeer Dec 02 '20 at 23:50
  • @OneCricketeer thanks for correction (I din't check all the JVM's distributions) , my above comment is available for AdoptOpenJDK and possible other distributions. If you want to check if this computation is true for other JVM's then, you can list the JVM's flags java -XX:+PrintFlagsFinal (for Molenpad) – Octavian R. Dec 03 '20 at 07:40
  • @Octa The percentage flags were backported around 8u192. Any earlier JDK8 releases didn't have it for any distribution, AFAIK – OneCricketeer Dec 03 '20 at 08:06
  • @OneCricketeer I see, (I think I remember something like this also for AdoptOpenJDK 1.8), then the usage of -XX:+PrintFlagsFinal before using the -XX:MaxRAMPercentage should solve this problem. If it's not there, then either use a newer version of JVM either he should set -Xmx – Octavian R. Dec 03 '20 at 08:10

1 Answers1

5

whether, in general terms, setting the -Xmx setting is too high for a container whose memory limit is 20GB

It depends. An application can use less RAM than the specified -Xmx, as well as 2x or 3x more RAM than the specified -Xmx. I've seen many applications of both kinds.

See what takes memory in a Java process.

Instead of trying to guess an appropriate heap size basing on the given container limit (those can be completely unrelated), why don't you set -Xmx to the value, which is comfortable enough for your particular application? I mean, if your application works fine with just 8 GB heap, there is no need to give it more, even if the container permits.

Is it generally the case that you use either MaxRAM or -Xmx, or is there any benefit to setting both?

Setting both is meaningless, as Xmx overrides MaxRAM.

I were to use MaxRAM instead of -Xmx, how would java allocate memory to the heap? Is there a simple algorithm for this, for example, 50% of the MaxRAM setting?

See What is the difference between xmx and MaxRAM JVM parameters?

Will java manage memory any more efficiently doing it that way?

No. MaxRAM only affects calculation of the heap size and the default garbage collector (when not explicitly specified).

apangin
  • 92,924
  • 10
  • 193
  • 247