Bitecode blog

Knowledge for JVM-hungry people

Introduction

Everyone knows what JAVA_OPTS is, but have you ever heard about JAVA_TOOL_OPTIONS?

Over the years, the way we run JVM has changed. With demand for running the aps in containers, JAVA_TOOL_OPTIONS environment variable might be handy. In this short article I will try to explain the reasons for using it.

What is JAVA_TOOL_OPTIONS environment variable and how it is different to JAVA_OPTS?

After using Apache Tomcat for a longer time, one might have an illusion that JAVA_OPTS is an environment variable and is picked by JVM when the app starts. In fact, it is not. It is catalina sh/bat starter that passes JAVA_OPTS content to the start up command line.

Contrary JAVA_TOOL_OPTIONS once setup is read by the JVM (in JNI_CreateJavaVM) and prepended to other options supplied in execution chain.

By java documentation JAVA_TOOL_OPTIONS

This environment variable allows you to specify the initialization of tools, specifically the launching of native or Java programming language agents using the -agentlib or -javaagent options.

This often happens with applications that use embedded VMs (meaning they use the Java Native Interface (JNI) Invocation API to start the VM), or where the startup is deeply nested in scripts. In these environments the JAVA_TOOL_OPTIONS environment variable can be useful to augment a command line.

In short, JAVA_TOOL_OPTIONS is a special environment variable which when set is used as if we write it’s content in JVM args.

Real life examples

There are scenarios when you would like to pass an argument to java app, but you can’t modify execution params. This can be due to the complexity of how the command line is generated, or sometimes JVM is executed by third party app, and we can’t adjust command line as it’s hardcoded. In those scenarios special JAVA_TOOL_OPTIONS environment variable shines.

Say you want to provide different memory configurations for different environments, but you don’t want to modify Dockerfile (and you are not using percentage settings). Normally you would modify the existing ENTRYPOINT in Dockerfile like below, e.g:

CMD ["java", "-Xmx1G", "-jar", "app.jar"]

but what if you want to keep Dockerfile intact.

You can take advantage of using JAVA_TOOL_OPTIONS and specified the necessary params there:

`export JAVA_TOOL_OPTIONS="-Xmx1G"`

Heap can be configured differently for specific environment:

      ...
      containers:
        - name: java-app
          image: your-java-app-image:latest
          env:
            - name: JAVA_TOOL_OPTIONS
              value: "-Xmx1G"
      ...

Using JAVA_TOOL_OPTIONS gives much finer control plus allowed to not overcomplicate the existing Dockerfile:

CMD ["java", "-jar", "app.jar"]

Summary

JAVA_TOOL_OPTIONS enables you to inject JVM arguments without modifying the application’s command line. This is particularly useful for complex or embedded environments.

comments powered by Disqus