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

Zhe*_*lov 62 java javac java-9

Java 9 javac有一个新的标志--release:

> javac --help
...

--release <release>
    Compile for a specific VM version. Supported targets: 6, 7, 8, 9
Run Code Online (Sandbox Code Playgroud)

-source-target旗帜有什么不同?它只是一个捷径-source X -target X吗?

Li3*_*357 78

不完全是.

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版本并允许在旧版本上执行.由于经常被遗忘,因此决定添加一个命令行选项,该选项执行所有必要的操作以正确交叉编译.

进一步阅读邮件列表Oracle Docs.最初的错误是在这里提交的.请注意,由于此选项的集成,JDK构建已捆绑了旧版本的平台API的描述,在"风险和假设"部分中提到.这意味着您不需要在计算机上安装旧版本以进行交叉编译.

  • 不,它们不会出现在 jre 8 二进制文件中 (2认同)
  • @JoseCifuentes,这里的“平台 API”给出了 JDK API 的版本,没有“--release”标志,将从用于编译的 JDK 推断出来,它通常与您使用“-source”和“-target”定位的 JDK 不同。如果您碰巧使用从未在 JDK 中引入的类/方法,那么这可能会困扰您。如果编译器选择了在更高版本中添加的方法而不是之前版本中添加的方法,则这是非常微妙的,从而默默地破坏了二进制兼容性。 (2认同)

Zhe*_*lov 17

--release X更不仅仅是一个快捷方式-source X -target X,因为-source-target没有足够的安全编译为较旧版本.您还需要设置一个-bootclasspath必须与旧版本对应的标志(这个标志经常被遗忘).因此,在Java 9他们做了一个--release标志,它是一个替代三个标志:-source,-target-bootclasspath.

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

javac --release 7 <source files>
Run Code Online (Sandbox Code Playgroud)

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