Java 9的javac
新增了一个标志--release
:
> javac --help
...
--release <release>
Compile for a specific VM version. Supported targets: 6, 7, 8, 9
这与 -source
和 -target
标志有何不同? 它只是 -source X -target X
的快捷方式吗?
Java 9的javac
新增了一个标志--release
:
> javac --help
...
--release <release>
Compile for a specific VM version. Supported targets: 6, 7, 8, 9
这与 -source
和 -target
标志有何不同? 它只是 -source X -target X
的快捷方式吗?
--release
:--release
,它可以自动配置编译器生成可以链接到给定平台版本实现的类文件。对于在javac中预定义的平台,--release N
等同于-source N -target N -bootclasspath <bootclasspath-from-N>
。(强调是我的)-source N -target N
。添加这个选项的原因在“动机”部分中说明:
简而言之,仅指定源和目标选项不足以进行交叉编译。因为
javac
提供了两个命令行选项,-source
和-target
,用于选择编译器接受的 Java 语言版本和生成的类文件版本。然而,默认情况下,javac
编译针对最近版本的平台 API。因此,编译后的程序可能会意外使用仅在当前平台版本中可用的 API。这样的程序无法在旧版本的平台上运行,无论传递给-source
和-target
的值是什么。这是一个长期的易用性问题,因为用户希望通过使用这些选项获得可以在指定平台版本上运行的类文件。
javac
默认编译最新的平台 API,无法保证在旧版本上运行。您还需要指定与旧版本对应的 -bootclasspath
选项才能正确地进行交叉编译。这将包括正确的 API 版本进行编译,并允许在旧版本上执行。由于经常被遗忘,因此决定添加一个命令行选项来完成正确进行交叉编译所需的所有必要操作。--release
标记,那么使用JDK API版本将根据编译时使用的JDK来推断,这通常与你使用-source
和-target
指定的JDK不同。如果你使用了从未出现在目标JDK中的类/方法,就可能会出现问题。尤其是当编译器选择一个后来版本中添加的方法重载而不是你原本想用的早期版本时,可能会悄悄地破坏二进制兼容性。 - Oliver Gondža--release X
不仅仅是-source X -target X
的快捷方式,因为-source
和-target
并不能安全地编译到旧版本。您还需要设置一个-bootclasspath
标志,该标志必须对应于旧版本(通常会忘记这个标志)。因此,在Java 9中,他们制作了一个单一的--release
标志,该标志替代了三个标志:-source
、-target
和-bootclasspath
。
所以,这是编译到Java 1.7的示例:
javac --release 7 <source files>
请注意,您甚至不需要在计算机上安装JDK 7。 JDK 9已经包含了所需的信息,以防止您意外链接到在JDK 7中不存在的符号。
另一个重要的区别是,只有在使用--release
编译时才能使用公共API:
> javac --add-exports java.base/sun.invoke=ALL-UNNAMED --release 11 Main.java
error: exporting a package from system module java.base is not allowed with --release
1 error
如果您想使用内部API,您必须移除选项--release
:
> javac --add-exports java.base/sun.invoke=ALL-UNNAMED Main.java
or> javac --add-exports java.base/sun.invoke=ALL-UNNAMED -source 11 -target 11 Main.java