Apache Tomcat on Azul Platform Prime

Tomcat works well on Azul Platform Prime and especially instances with heap sizes of dozens or more GBytes benefit from Azul Platform Prime's pauseless Garbage Collection implementation.

There is just one detail you should be aware of when using Azul Zulu Prime JVM: It allocates the complete Java heap as defined by -Xmx on the command line on process start and it ignores the -Xms parameter.

Because of that, it is required that you define the heap size for your Tomcat java process by the Tomcat CATALINA_OPTS setting and not by the Tomcat JAVA_OPTS setting.

In the following example configuration the Tomcat java process is set to 32 GB heap size. You'll notice another heap size setting in JAVA_OPTS which is the one the small Tomcat helper process will use on shutdown. I added this to avoid uncertainty about the default heap size as that can differ depending on the system environment.

Tomcat configuration file tomcat/bin/setenv.sh:

-Xmx=32G \
-Xlog:gc,safepoint:$CATALINA_HOME/logs/gc.log \

-Xmx512M \

This specialty of the Tomcat configuration is more critical on Azul Zulu Prime JVM than on other JVMs due to its full heap allocation on start. It is documented in section 3.3 Other variables of https://tomcat.apache.org/tomcat-9.0-doc/RUNNING.txt (linked from https://tomcat.apache.org/tomcat-9.0-doc/setup.html): 

Note: Do not use JAVA_OPTS to specify memory limits.
You do not need much memory for a small process that is
used to stop Tomcat. Those settings belong to CATALINA_OPTS.


Linux Containers

In combination with Linux containers or Linux cgroups, one additional detail becomes important: When no -Xmx is defined on the command line, the default heap size will be 25% of the container memory limit without any further upper limit. That means even the tiny shutdown helper process of Tomcat will then try to allocate 25% of your container size which will cause problems as most likely the main Tomcat process is already taking most of the container memory.

In those cases you will see the following error when trying to shut down Tomcat with "catalina.sh stop" or you will even see the Linux memory killer becoming active:

[-UseZST][ERROR] Available physical memory is not enough to fund the backing storage
(have 5153960755 bytes, need 34359738368 bytes)
Error occurred during initialization of VM
Failed to initialize memory management system

This can be prevented with the same configuration in tomcat/bin/setenv.sh as explained above. But for containers or cgroups, the following setting instead may be better for your use case as it adjusts dynamically to the container size:

-XX:MaxRAMPercentage=75.0 \
-Xlog:gc,safepoint:$CATALINA_HOME/logs/gc.log \

-XX:MaxRAMPercentage=1.0 \

The 75% of the container memory as heap size is just an example and your use case might need some adjustment, especially when other processes are run in parallel inside the container.

Note: Don't mix -Xmx and -XX:MaxRAMPercentage in the same configuration.

To check which heap size (in Bytes) is effectively selected by an active java process, use the following:

jcmd JVMID VM.flags | tr ' ' '\n' | grep MaxHeapSize

With  JVMID either the process ID or the classname as shown by running jcmd without any options.


Heap Elasticity Feature

An alternative to the described solution above can be in some environments the new Heap Elasticity feature available since Azul Platform Prime 21.05. That supports the -Xms parameter, but is not enabled by default. See Heap Elasticity for details.

Add Comment



Please sign in to leave a comment.

Was this article helpful?
0 out of 0 found this helpful