运行 单文件源代码 Java 程序时如何传递编译器选项?

How to pass compiler options when running a single-file source-code Java program?

我想使用 JEP 330 到 运行 具有 Java (>= 11) 的单文件源代码程序。

这样做,我想传递编译器 (javac) 而不是 运行time (java) 理解的选项,例如-XDsuppressNotes。这导致例如以下调用失败:

java --enable-preview --source=12 -XDsuppressNotes Test.java

Unrecognized option: -XDsuppressNotes
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.

在这种情况下如何指定此类特定于编译器的选项?

How can I specify such compiler-specific option in this case?

简答:你不能。

这个JEP的目标不是要取代javac!只是为了更方便,尤其是在刚开始编程的情况下达到"run this program".

的目的

JEP-330 与标准 javac -> java 链相比有一系列限制。 JEP 本身的引述:

As of JDK 10, the java launcher operates in three modes: launching a class file, launching the main class of a JAR file, or launching the main class of a module. Here we add a new, fourth mode: launching a class declared in a source file.

...

In source-file mode, the effect is as if the source file is compiled into memory, and the first class found in the source file is executed. For example, if a file called HelloWorld.java contains a class called hello.World, then the command

java HelloWorld.java

is informally equivalent to

javac -d <memory> HelloWorld.java

java -cp <memory> hello.World

Any arguments placed after the name of the source file in the original command line are passed to the compiled class when it is executed. For example, if a file called Factorial.java contains a class called Factorial to calculate the factorials of its arguments, then the command

java Factorial.java 3 4 5

is informally equivalent to

javac -d <memory> Factorial.java

java -cp <memory> Factorial 3 4 5

In source-file mode, any additional command-line options are processed as follows:

  • The launcher scans the options specified before the source file for any that are relevant in order to compile the source file. This includes: --class-path, --module-path, --add-exports, --add-modules, --limit-modules, --patch-module, --upgrade-module-path, and any variant forms of those options. It also includes the new --enable-preview option, described in JEP 12.

  • No provision is made to pass any additional options to the compiler, such as -processor or -Werror.

...


换句话说,运行宁单文件源代码 Java 程序时应牢记某些限制:

  • 没有外部 classes,仅限单文件程序 - 你不能在其他文件中调用任何其他 classes比你正在执行的文件。

  • 没有 class 文件可用 - 以这种方式调用 java 工具不会产生任何 *.class 您可以在工作目录中看到的文件。

  • 如果现有 class 文件存在于 class 路径中,您将被迫使用它 - 对于一个文件,比如说SampleClass.java,如果存在 class 文件,例如 SampleClass.class,您可能无法调用 java 工具以 运行 源文件模式下的源文件.

  • 文件名,而不是 class 名称 - java 工具考虑文件名而不是文件名class正在执行源文件。

  • 文件中的第一个 class,不匹配文件-class 名称 - class 加载程序不再通过匹配文件名和class名称来确定要执行的class。文件中的第一个 class 将是 运行、

  • 对源文件中的 public 个文件没有限制 - 而 javac 关心 public 的数量class在源文件中,java不在乎。

  • 您不能传递某些特定于编译器的参数 - 您可以传递给 [=] 的 -Werror-nowarn 等参数10=],可能不会被 java 工具传递(或识别)。

Short answer: you can't.

错了,你可以

奇怪,--source 11 选项必须出现两次:Beforeafter 所有其他选项:

#!/usr/bin/java --source 11 -ea -cp path/to/jars --source 11
// There appears to be a bug in JDK 11.0.2 single-file mode: The first option must
// be "--source 11" to enable single-file mode, but then the "-cp" DISABLES
// single-file mode (bug). The workaround is to repeat the "--source 11" option
// right after the "-cp" option.

测试

java version "11.0.2" 2019-01-15 LTS
GNU bash, Version 4.4.12(3)-release (x86_64-unknown-cygwin)