Tips for running Java on Platform.sh

Goal

This tutorial will explain some Java commands and some recommendations to optimize the process of running your Java applications safety on Platform.sh.

Assumptions

  • You either have a Java application that you want to run on Platform.sh, or you already have a Java application already running on Platform.sh

  • A text editor of your choice.

Steps

Once you have your Java application running on Platform.sh, there are several steps you should take to optimize the application runtime.

Minimum requirement (Memory)

The first one is Xmx, which defines the maximum size that the JVM can use. The optimal value can be derived from the application’s generated configuration files and will scale with your container size automatically.

To extract the appropriate value on the command line, use $(jq .info.limits.memory /run/config.json).

The second parameter is ExitOnOutOfMemoryError. When you enable this option, the JVM exits on the first occurrence of an out-of-memory error. Platform.sh will restart the application automatically.

These are the basic recommended parameters for running a Java application. So, the command will start with:

java -jar -Xmx$(jq .info.limits.memory /run/config.json)m -XX:+ExitOnOutOfMemoryError //The rest of the arguments and the jar file.

Garbage collector (Optional)

When migrating the application to a cloud environment, it is often essential to analyze the Garbage Collector’s log and behavior. For this, there are two options:

  • Placing the log into the Platform.sh app.log file (which captures STDOUT).
  • Creating a log file specifically for the GC.

To use the STDOUT log, you can add the parameter -XX: + PrintGCDetails, E.g.:

java -jar -Xmx$(jq .info.limits.memory /run/config.json)m -XX:+ExitOnOutOfMemoryError -XX:+PrintGCDetails //The rest of the arguments and the jar file.

Java supports a number of different garbage collection strategies. Which one is optimal for your application will vary depending on your available memory, Java version, and application profile. Determining which is best for your application is out of scope, but the main options and how to enable them are:

Name Command Flag Description
Serial Garbage Collector -XX:+UseSerialGC This is the simplest GC implementation, as it basically works with a single thread.
Parallel Garbage Collector -XX:+UseParallelGC Unlike Serial Garbage Collector, this uses multiple threads for managing heap space. But it also freezes other application threads while performing GC.
CMS Garbage Collector -XX:+USeParNewGC The Concurrent Mark Sweep (CMS) implementation uses multiple garbage collector threads for garbage collection. It’s for applications that prefer shorter garbage collection pauses, and that can afford to share processor resources with the garbage collector while the application is running.
G1 Garbage Collector -XX:+UseG1GC Garbage First, G1, is for applications running on multiprocessor machines with large memory space.

The default stragtegy on Java 9 and later is G1. The GC strategy to use can be set in the start line with:

Serial

java -jar -Xmx$(jq .info.limits.memory /run/config.json)m -XX:+ExitOnOutOfMemoryError -XX:+PrintGCDetails -XX:+UseSerialGC //The rest of the arguments and the jar file.

Parallel Garbage Collector

java -jar -Xmx$(jq .info.limits.memory /run/config.json)m -XX:+ExitOnOutOfMemoryError -XX:+PrintGCDetails -XX:+UseParallelGC //The rest of the arguments and the jar file.

CMS Garbage Collector

java -jar -Xmx$(jq .info.limits.memory /run/config.json)m -XX:+ExitOnOutOfMemoryError -XX:+PrintGCDetails -XX:+USeParNewGC //The rest of the arguments and the jar file.

G1

java -jar -Xmx$(jq .info.limits.memory /run/config.json)m -XX:+ExitOnOutOfMemoryError -XX:+PrintGCDetails -XX:+UseG1GC //The rest of the arguments and the jar file.

Java 8 Optimization

Ideally, all applications should run the latest LTS release of the JVM at least. That is currently Java 11. Java 11 has a number of performance improvements, particularly on container-based environments such as Platform.sh.

However, in many cases, this is not possible. If you are still running on Java 8 there are two additional considerations.

The default garbage collector for Java 8 is Parallel GC. In most cases G1 will offer better performance. We recommend enabling it, as above.

Furthermore, there is the UseStringDeduplication flag which works to eliminate duplicate Strings within the GC process. That flag can save between 13% to 30% of memory, depending on application. However, this can impact on the pause time of your app.

java -jar -Xmx$(jq .info.limits.memory /run/config.json)m -XX:+UseG1GC -XX:+UseStringDeduplication -XX:+ExitOnOutOfMemoryError -XX:+PrintGCDetails

References

1 Like