使用 Java 11 时 JDK_JAVA_OPTIONS 和 JAVA_TOOL_OPTIONS 有什么区别?

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

使用 Java 11 时 JDK_JAVA_OPTIONS and JAVA_TOOL_OPTIONS 的确切区别是什么?

我正在使用一个小型测试程序:

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

两个环境变量看起来是一样的,只是输出略有不同。这让我相信他们可能有不同的用例:

$ 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.

似乎 JDK_JAVA_OPTIONS 优先于 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

但最终命令行获胜:

$ 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

构建时,只有 JAVA_TOOL_OPTIONS 被读取:

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

我目前正在使用 AdoptOpenJDK 11 build 28。

  • JDK_JAVA_OPTIONS 仅由 java 启动器拾取,因此将它用于您只想应用(或仅有意义)java 启动命令的选项。这个变量在 JDK 9+ 上也是新的,并且会被早期的 JDK 版本忽略。因此,它在从旧版本迁移到 9+ 时很有用。
  • JAVA_TOOL_OPTIONS 也被其他 java 工具使用,例如 jarjavac 所以它应该用于您想要应用的标志(并且是有效的) 所有这些 java 工具。

@gjoranv 的回答解释了这两个变量之间的功能差异。

我认为输出的差异源于以下几点:

  1. 这两个变量似乎在启动过程中的不同点执行。

  2. JDK_JAVA_OPTIONS 文档说:

    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.

    这一行:

     Error: Cannot specify main class in environment variable JDK_JAVA_OPTIONS
    

    是警告用户可能试图通过该变量进行破坏的错误消息。

    我认为 JDK_JAVA_OPTIONS 优先,部分原因相同。