使用 Java 11 时,JDK_JAVA_OPTIONS 和 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 工具使用,例如 jar
和 javac
,因此它应该用于您想要应用于(并且有效)到所有这些 java 工具的标志。@gjoranv 的回答解释了两个变量之间的功能差异。
我认为输出的差异源于以下几点:
这两个变量似乎是在启动过程中的不同点实现的。
JDK_JAVA_OPTIONS
文档说:
为了减少潜在的误用 JDK_JAVA_OPTIONS 行为,环境变量中不允许使用指定主类(例如 -jar)或导致 java 启动器退出而不执行主类(例如 -h)的选项。如果这些选项中的任何一个出现在环境变量中,启动程序将中止并显示错误消息。
这一行:
Error: Cannot specify main class in environment variable JDK_JAVA_OPTIONS
是警告用户可能试图通过该变量造成混乱的错误消息。
我认为
JDK_JAVA_OPTIONS
优先,部分原因相同。JAVA_TOOL_OPTIONS
的优先级较低,如此处所述
由于在调用 JNI_CreateJavaVM 函数时会检查此环境变量,因此它不能用于使用通常由启动器处理的选项来扩充命令行,例如,使用 -client 选项或-服务器选项。