Apache Tomcat on Azul Zing

Tomcat works well on Azul Zing and especially instances with heap sizes of tens or more GBytes benefit from the pauseless Garbage Collection implementation of Azul Zing.

There is just one detail you should be aware of when using older Azul Zing versions, those before 21.07: On those old versions, it allocates the complete Java heap as defined by -Xmx on the command line on process start and it ignores the -Xms parameter. With 21.07 and newer versions, the heap is allocated elastically on demand within the user-defined -Xms and -Xmx range. See Heap-Size Settings for details.

As solution, the settings described in the following section are required on those old Azul Zing versions and also when the optional ZST component is installed. On current versions, this setting is not needed in most cases, but it still can be useful and to learn about this specialty in Tomcat configuration, which can be relevant also on OpenJDK, reading is recommended:

Setting the Java Heap Size for Tomcat

It's recommended to 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 for starting and stopping the large main process. 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 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 helper process of Tomcat will then try to allocate 25% of your container size on old Azul Zing versions, 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 start or shut down Tomcat with "catalina.sh start" or "catalina 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.

Add Comment



Please sign in to leave a comment.

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