javajvmjvm-argumentsjava-11

What is the difference between JDK_JAVA_OPTIONS and JAVA_TOOL_OPTIONS when using Java 11?


What is the exact difference between JDK_JAVA_OPTIONS and JAVA_TOOL_OPTIONS when using Java 11?

I'm using a tiny test program:

public class Foo {
  public static final void main(String[] args) {
    System.out.println("arg: " + System.getProperty("arg"));
  }
}

The two environment variables seem to do the same, but the output is slightly different. That makes me believe they might have different use cases:

$ JDK_JAVA_OPTIONS="-Darg=jdk" java Foo
NOTE: Picked up JDK_JAVA_OPTIONS: -Darg
arg: jdk

$ JAVA_TOOL_OPTIONS="-Darg=tool" java Foo
Picked up JAVA_TOOL_OPTIONS: -Darg
arg: tool

$ JDK_JAVA_OPTIONS="illegalArg" java Foo
NOTE: Picked up JDK_JAVA_OPTIONS: illegalArg
Error: Cannot specify main class in environment variable JDK_JAVA_OPTIONS

$ JAVA_TOOL_OPTIONS="illegalArg" java Foo
Picked up JAVA_TOOL_OPTIONS: illegalArg
Unrecognized option: illegalArg
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.

It seems like JDK_JAVA_OPTIONS have precedence over JAVA_TOOL_OPTIONS:

$ JDK_JAVA_OPTIONS="-Darg=jdk" JAVA_TOOL_OPTIONS="-Darg=tool" java Foo
NOTE: Picked up JDK_JAVA_OPTIONS: -Darg=jdk
Picked up JAVA_TOOL_OPTIONS: -Darg=tool
arg: jdk

But ultimately the command line wins:

$ JDK_JAVA_OPTIONS="-Darg=jdk" JAVA_TOOL_OPTIONS="-Darg=tool" java -Darg=cmd Foo
NOTE: Picked up JDK_JAVA_OPTIONS: -Darg=jdk
Picked up JAVA_TOOL_OPTIONS: -Darg=tool
arg: cmd

When building, though, only JAVA_TOOL_OPTIONS is read:

$ JDK_JAVA_OPTIONS="-Darg=jdk" JAVA_TOOL_OPTIONS="-Darg=tool" javac Foo.java
Picked up JAVA_TOOL_OPTIONS: -Darg=tool

I'm currently using AdoptOpenJDK 11 build 28.


Solution

  • The functional difference between the two variables is explained by @gjoranv's answer.

    The differences in the output I think stem from the following:

    1. The two variables seem to be implemented in different points in the launching process.

    2. The JDK_JAVA_OPTIONS documentation says:

      In order to mitigate potential misuse of JDK_JAVA_OPTIONS behavior, options that specify the main class (such as -jar) or cause the java launcher to exit without executing the main class (such as -h) are disallowed in the environment variable. If any of these options appear in the environment variable, the launcher will abort with an error message.

      This line:

       Error: Cannot specify main class in environment variable JDK_JAVA_OPTIONS
      

      is the error message that warns the user of a potential attempt to do mayhem via that variable.

      I think that JDK_JAVA_OPTIONS takes precedence, in part for the same reason.