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

Java 9编译器中的--release标志是什么?,java,javac,java-9,Java,Javac,Java 9,Java 9的javac有一个新的标志——release: > javac --help ... --release <release> Compile for a specific VM version. Supported targets: 6, 7, 8, 9 > javac --add-exports java.base/sun.invoke=ALL-UNNAMED --release 11 Main.java error: exporting a p

Java 9的
javac
有一个新的标志
——release

> javac --help
...

--release <release>
    Compile for a specific VM version. Supported targets: 6, 7, 8, 9
> 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
> javac --add-exports java.base/sun.invoke=ALL-UNNAMED Main.java
>javac——帮助
...
--释放
为特定VM版本编译。支持的目标:6、7、8、9
它与
-source
-target
标志有何不同?它只是
-源X-目标X的快捷方式吗?

不完全是

定义此新命令行选项,
--release

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

所以不,它并不等同于
-source N-target N
。增加的原因在“动机”一节中说明:

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

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

进一步阅读和讨论。最初的bug被归档了。请注意,自从集成了此选项之后,JDK构建与“风险和假设”一节中提到的较旧版本的平台API的描述捆绑在一起。这意味着交叉编译不需要在计算机上安装旧版本。

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

这是一个编译为Java 1.7的示例:

javac --release 7 <source files>
如果要使用内部API,必须删除选项
--release

> javac --help
...

--release <release>
    Compile for a specific VM version. Supported targets: 6, 7, 8, 9
> 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
> javac --add-exports java.base/sun.invoke=ALL-UNNAMED Main.java


一个疑问是,是否有可能在代码中使用jdk 9-11的功能,而它仍然在java runtime 8上运行?不,它们不会出现在jre 8二进制文件中,您认为“平台API”是什么?是字节码级别的吗?或者与底层x86平台或操作系统API相关的东西?@JoseCifuentes,这里的“平台API”是指JDK API,它的版本(没有
--release
标志)将从用于编译的JDK中推断出来,而JDK通常与使用
-source
-target
的JDK不同。如果您碰巧使用了从不在JDK中引入的类/方法,而不是您的目标类/方法,这可能会影响您。如果编译器选择的方法重载是在较新版本中添加的,而不是在先前版本中添加的,则这是非常微妙的,从而悄悄地破坏了二进制兼容性。有关Maven的相关问题: