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

2022-08-31 08:44:30

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


答案 1

不完全是。

JEP 247:针对旧平台版本编译定义了这个新的命令行选项:--release

我们定义了一个新的命令行选项,它会自动配置编译器以生成类文件,这些文件将链接到给定平台版本的实现。对于 中预定义的平台,--release N 等效于 -source N -target N -bootclasspath <bootclasspath-from-N>。(强调我的)--releasejavac

所以不,它不等同于 。此添加的原因在“动机”部分中说明:-source N -target N

javac提供了两个命令行选项,和 ,分别可用于选择编译器接受的 Java 语言版本及其生成的类文件的版本。但是,默认情况下,会针对最新版本的平台 API 进行编译。因此,编译的程序可能会意外地使用仅在当前版本的平台中可用的 API。此类程序无法在较旧版本的平台上运行,无论传递给 和 的值如何。选项。这是一个长期的可用性痛点,因为用户希望通过使用这些选项,他们将获得可以在指定平台版本上运行的类文件。-source-targetjavac-source-target

简而言之,指定源选项和目标选项不足以进行交叉编译。由于默认情况下,会针对最新的平台 API 进行编译,因此无法保证它们在旧版本上运行。您还需要指定与旧版本对应的选项才能正确交叉编译。这将包括正确的API版本进行编译,并允许在旧版本上执行。由于它经常被遗忘,因此决定添加一个命令行选项,该选项可以执行所有必要的操作以正确进行交叉编译。javac-bootclasspath

进一步阅读邮件列表Oracle 文档。原始错误已在此处提交。请注意,自集成此选项以来,JDK 版本已与旧版本的平台 API 的描述捆绑在一起,如“风险和假设”一节所述。这意味着您不需要在计算机上安装旧版本即可进行交叉编译。


答案 2

--release X不仅仅是一个快捷方式,因为并且不足以安全地编译为较旧的版本。您还需要设置一个必须与旧版本相对应的标志(并且此标志经常被遗忘)。因此,在Java 9中,他们制作了一个标志,该标志可以替代三个标志:,和。-source X -target X-source-target-bootclasspath--release-source-target-bootclasspath

所以,这是一个编译到Java 1.7的例子:

javac --release 7 <source files>

请注意,您甚至不需要在计算机上安装JDK 7。JDK 9 已经包含了所需的信息,以防止您意外链接到 JDK 7 中不存在的符号。

另一个重要的区别是,在编译时,您只能使用公共 API:--release

> 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

> javac --add-exports java.base/sun.invoke=ALL-UNNAMED -source 11 -target 11  Main.java

推荐