【问题标题】:What is the --release flag in the Java 9 compiler?Java 9 编译器中的 --release 标志是什么?
【发布时间】:2017-08-23 11:43:42
【问题描述】:

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 javac java-9


【解决方案1】:

不完全是。

JEP 247: Compile for Older Platform Versions 定义了这个新的命令行选项,--release

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

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

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

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

进一步阅读in the mailing listOracle Docs。原始错误已提交here。请注意,自从集成此选项以来,JDK 构建与旧版本平台 API 的描述捆绑在一起,在“风险和假设”部分中提到。这意味着您不需要在计算机上安装旧版本即可进行交叉编译。

【讨论】:

  • 有一个疑问,是否可以在代码中使用 jdk 9-11 中的功能并且它仍然可以在 java 运行时 8 上运行?
  • 不,它们不会出现在 jre 8 二进制文件中
  • 你们对“Platform API”有什么看法?是字节码级别的东西吗?还是与底层 x86 平台或操作系统 API 相关的东西?
  • @JoseCifuentes,这里的“Platform API”给出了 JDK API 的版本,没有 --release 标志,将从用于编译的 JDK 中推断出来,这通常不同于您使用 -source 定位的 JDK和-target。如果您碰巧使用了在 JDK 中引入的类/方法,那么这可能会咬您一口,然后是您的目标。如果编译器选择的方法 overload 是在更高版本中添加的,而不是您之前想要的方法,这会更加微妙,从而默默地破坏二进制兼容性。
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-04
    • 1970-01-01
    相关资源
    最近更新 更多