Apache Tomcat on Zing

Tomcat works well on Zing and especially instances with heapsizes of dozens or more GBytes benefit from Zing's pauseless Garbage Collection implementation.

There is just one detail you should be aware of when using Zing: 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 heapsize 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 heapsize. You'll notice another heapsize 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 heapsize 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 Zing due to its full heap allocation on start, than on other JVMs. 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 \
-Xlog:gc,safepoint:$CATALINA_HOME/logs/gc.log \

-XX:MaxRAMPercentage=1 \

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 heapsize (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