Java 9编译器中的--release标志是什么?

136

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 的快捷方式吗?


OpenJDK还是Oracle? - Sam Ginrich
2个回答

161
不完全正确。 JEP 247: 面向旧平台版本编译定义了一个新的命令行选项--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 版本进行编译,并允许在旧版本上执行。由于经常被遗忘,因此决定添加一个命令行选项来完成正确进行交叉编译所需的所有必要操作。
更多信息请参阅邮件列表(链接1)和 Oracle 文档(链接2)。原始 bug 报告在此(链接3)。请注意,自从添加了该选项后,JDK 构建已捆绑了旧版本平台 API 的描述,位于“风险和假设”部分下面。这意味着您不需要在计算机上安装旧版本即可进行交叉编译。

1
有一个疑问,是否可以在代码中使用JDK 9-11的功能,并且仍然在Java运行时8上运行? - Cristiano
2
不,它们不会出现在jre 8二进制文件中。 - Rogue
1
“Platform API”是什么意思?是指字节码级别的东西吗?还是与底层x86平台或操作系统API相关的东西? - Jose Cifuentes
3
这段话是在讨论使用Java编程时可能会遇到的问题。如果你没有指定--release标记,那么使用JDK API版本将根据编译时使用的JDK来推断,这通常与你使用-source-target指定的JDK不同。如果你使用了从未出现在目标JDK中的类/方法,就可能会出现问题。尤其是当编译器选择一个后来版本中添加的方法重载而不是你原本想用的早期版本时,可能会悄悄地破坏二进制兼容性。 - Oliver Gondža

54

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接