Blogpost

Passage of time

3 minute read

Tweaking JVM options

Find out how JVM tuning is made easy on our platform.

While the Java Virtual Machine is a true genius at managing memory consumption (garbage collection), code optimizations and many more, it usually is a good idea to tune some of it’s settings.

The list of configurable JVM parameters is very long, for this article we’ll stick to some of the most important params. First, go to your application detail page and click on the “Config” tab. Click on the “Import” button and paste the following entries:

JVM_XMX="4096m"
JVM_XMS="4096m"
JVM_PRINTGCDETAILS="1"
JVM_PRINTGCTIMESTAMPS="1"
JVM_PRINTAPPSTOPTIME="1"
JVM_JMX="1"
JVM_JMXPORT="1099"
JVM_OPTIONS_PREFIX="-"
JVM_OPTIONS_SUFFIX=" "
JVM_OPTIONS_FILE=".jvmoptions"

The last three variables are there to make everything reusable across your different java applications. We’ll get back to that later on.

Please be careful now: the “Replace variables” button actually wipes all your current variables and only retains the ones you imported. If this is not what you want, you should click the “Append variables” button. You’ll then get an overview of your imported variables merged with the already existing ones. In case of conflicts you’ll see a warning. When everything is ok, you can click the “Import variables” button. After clicking the “Save changes” and “Apply variables now” button, these variables are made available for your application.

Now click on the “Actions” tab in the top menu and then on “Custom actions” in the left menu. We’ll now create a re-usable custom action that makes the JVM options available for other actions. When you click the “Add custom action” button the action editor opens up. Paste the following script:

#!/bin/bash

set -e
set -x

OPTION_PREFIX_CHAR='{{JVM_OPTIONS_PREFIX}}'
OPTION_SUFFIX_CHAR='{{JVM_OPTIONS_SUFFIX}}'

add_to_array() {
  JAVAOPTS+=($1)
}

is_set() {
  [[ ! "${1}" = '' ]] && [[ ! "${1}" =~ ^\{\{.* ]]
}

if is_set "$OPTION_SUFFIX_CHAR" ; then
  echo "Option suffix is set"
else
  echo "Option suffix not set, setting to space"
  OPTION_SUFFIX_CHAR=" "
fi

echo "Option prefix = '$OPTION_PREFIX_CHAR'"
echo "Option suffix = '$OPTION_SUFFIX_CHAR'"

# First, collect all extra jvm parameters from the application configuration
# http://www.baeldung.com/jvm-parameters
XMX="{{JVM_XMX}}"
XMS="{{JVM_XMS}}"
XSS="{{JVM_XSS}}"
JMX="{{JVM_JMX}}"
JMX_PORT="{{JVM_JMXPORT}}"
PRINTGCDETAILS="{{JVM_PRINTGCDETAILS}}"
PRINTGCTIMESTAMPS="{{JVM_PRINTGCTIMESTAMPS}}"
PRINTAPPSTOPTIME="{{JVM_PRINTAPPSTOPTIME}}"

GC_COLLECTOR="UseSerialGC"
# -XX:+UseSerialGC
# -XX:+UseParallelGC
# -XX:+USeParNewGC
# -XX:+UseG1GC

JAVAOPTS=()

if is_set $XMX ; then
  add_to_array "Xmx=$XMX"
fi

if is_set $XMS ; then
  add_to_array "Xms=$XMS"
fi

if is_set $XSS ; then
  add_to_array "Xss=$XSS"
fi

if [ $JMX="1" ]; then
  add_to_array "com.sun.management.jmxremote.port=$JMX_PORT"
  add_to_array "com.sun.management.jmxremote.authenticate=false"
fi

if [ $PRINTGCDETAILS="1" ]; then
  add_to_array "XX:-PrintGCDetails"
fi

if [ $PRINTGCTIMESTAMPS="1" ]; then
  add_to_array "XX:-PrintGCTimeStamps"
fi

if [ $PRINTAPPSTOPTIME="1" ]; then
  add_to_array "XX:-PrintGCApplicationStoppedTime"
fi

if is_set $GC_COLLECTOR ; then
  add_to_array "XX:+$GC_COLLECTOR"
fi

echo "#######################"
echo "JVM PARAMETERS: "
CONCATENATED_JVM_PARAMS=""
for i in "${JAVAOPTS[@]}"
do
	PREFIX=$OPTION_PREFIX_CHAR
	
	# the jvm options that start with XX don't need the full prefix (eg -D), just a dash
    if [ ! -z $PREFIX ] && [ "${i:0:2}" == "XX" ]; then
	  PREFIX="-"
	fi
    CONCATENATED_JVM_PARAMS="$CONCATENATED_JVM_PARAMS$OPTION_SUFFIX_CHAR$PREFIX$i"
done
echo $CONCATENATED_JVM_PARAMS
echo "#######################"

if [ -f {{JVM_OPTIONS_FILE}} ]; then
  echo "Backing up previous options file"
  mv {{JVM_OPTIONS_FILE}} "{{JVM_OPTIONS_FILE}}-backup$(date +%s)"
fi

echo "Writing options to file: {{JVM_OPTIONS_FILE}}"

echo -e $CONCATENATED_JVM_PARAMS > {{JVM_OPTIONS_FILE}}

In short, this script writes all the JVM options to a file. Name this action something like “Generate and persist JVM options” and save it. Now open your scenario that starts/restarts your application and put the JVM options action in front. In the action that actually (re)starts your application, the JVM options are available by reading out the file like this: $(cat {{JVM_OPTIONS_FILE}})

For example: java -jar helloworld.jar $(cat {{JVM_OPTIONS_FILE}})

Earlier on, we also defined two variables ‘JVMOPTIONSPREFIX’ and ‘JVMOPTIONSSUFFIX’. In some cases you might want to have the options outputted in another format. This is easily and done by changing the option prefix and/or suffix in the application configuration. For example when you want to inject these options in the init file of a webserver like Tomcat, you can use ‘-D’ as option prefix and ‘\n’ as option suffix. This way, each option will be generated on a separate line starting with ‘-D’.