2

I'm deploying a Java Spring-Boot application as a Docker container to servers having 16 GB of memory.

The Docker server version is 19.03.12 on a Ubuntu 18.04.4 LTS. My Docker image has openjdk-11 as the Java runtime installed. The entrypoint is defined as:

ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "app.jar"]

I start the container without any restrictions to CPU and memory, but the application dies always with an OutOfMemoryError when the Heap space reaches 8 GB. There are running some other containers, but the system has still around 3-4 GB of free memory.

Why is the JVM inside the container somehow limited to use 8 GB of memory, although is 'sees' the entire 16 GB? What do I have to do that the JVM is allowed to consume as much memory the system provides?

Marcel Härle
  • 163
  • 2
  • 6
  • 7
  • Try setting -Xmx to something more than 8GB. Just add "-Xmx8G" to your ENTRYPOINT. – Oo.oO Jul 28 '20 at 12:05
  • 1
    I think your question is already answered here: https://stackoverflow.com/questions/4667483/how-is-the-default-max-java-heap-size-determined – Rishabh Sharma Jul 28 '20 at 12:06
  • It's not clear whether you expect your application to use more than 8G of heap. You may also want to set `-XX:+HeapDumpOnOutOfMemoryError ` and have a look at where the memory is going. – tgdavies Jul 28 '20 at 12:08

2 Answers2

1

You can use command line switches to adjust the heap size available for the JVM. For example, to set a 12GB maximum heap which leaves 4GB for the operating system and other JVM functions, add the command line argument -Xmx 12G.

There is no way to tell Java it can use as much memory as it wants, or as much as the operating system has installed - see Why does the (Sun) JVM have a fixed upper limit for memory usage (-Xmx)?

Joni
  • 101,441
  • 12
  • 123
  • 178
  • Hey, thanks for your answer. I'm aware of the -Xms and -Xmx JVM options. I was hoping that there is some generic way to force the system or JVM to push to the system's limits. So now I have to solve the problem to determine automatically the system's available memory on deployment in order to start the container with the required heap options, because the servers to not have all the same resources. – Marcel Härle Jul 29 '20 at 13:19
  • 1
    You don't always give the same amount of memory to the container? You can read the container's memory limit from `/sys/fs/cgroup/memory.max`. If the user does not set a memory limit, use `awk '/^MemTotal/ {print $2}' /proc/meminfo` – Joni Jul 29 '20 at 15:51
1

You are assuming that JVM gives your application to the entirety of available memory. It does not. In fact the amount of memory is deliberately capped - the exact value depends on the system. You can read more about determinig how much memory is actually available to your app here.

As for how to manually manage how much emory your app is able to access read this article. It has a nice explanation of JVM parameters.

Konrad Botor
  • 3,904
  • 1
  • 10
  • 21