根据JEP 295
任何 JDK 模块、类或用户代码的 AOT 编译都是实验性的,在 JDK 9 中不受支持。
要使用 AOTed java.base 模块,用户必须编译模块并将生成的 AOT 库复制到 JDK 安装目录或在 java 命令行中指定它。
我对上面的陈述感到困惑,如果 JDK 9 不支持 AOT,那么我们如何使用 AOT 编译模块?
我的第二个问题是,如果 AOT比 JIT 有很多优势,为什么 JDK 9 不支持它?
根据JEP 295
任何 JDK 模块、类或用户代码的 AOT 编译都是实验性的,在 JDK 9 中不受支持。
要使用 AOTed java.base 模块,用户必须编译模块并将生成的 AOT 库复制到 JDK 安装目录或在 java 命令行中指定它。
我对上面的陈述感到困惑,如果 JDK 9 不支持 AOT,那么我们如何使用 AOT 编译模块?
我的第二个问题是,如果 AOT比 JIT 有很多优势,为什么 JDK 9 不支持它?
先从你的问题回答后半部分。AOT 在与 Java 9 API 的兼容性方面并不完全成熟。链接的 JEP 中还列出了一些限制:
它仍然仅限于基于 64 位 Linux 的系统。
要使用 AOT 编译,用户需要使用同一个 JDK 进行编译和执行。用于编译的版本信息jaotc
作为库的一部分添加,并在加载时进行检查。如果 Java 运行时更新,则需要在执行之前重新编译 AOT 编译的模块。用于编译和执行的 JDK 版本不匹配可能会导致应用程序崩溃。
AOT 编译器目前不支持 Lambda 表达式和其他复杂的 Java 概念,它们在运行时使用动态生成的类。
要生成共享对象 (.so) 文件,需要libelf
预先安装系统。
的逻辑编译模式java.base
是分层 AOT,因为java.base
需要对方法进行 JIT 重新编译以达到最佳性能。只有在某些情况下,非分层 AOT 编译才有意义。这包括需要可预测行为的应用程序,当占用空间比峰值性能更重要时,或者对于不允许动态代码生成的系统。在这些情况下,需要在整个应用程序上进行 AOT 编译,因此在 JDK 9 中是实验性的。
这些限制可以在未来的版本中解决,那时我很确定该功能中的 Experimental 标签将被删除。
如果 JDK 9 不支持 AOT,那么我们如何使用 AOT 编译模块?
要使用 AOT,需要使用jaotc
编译器编译应用程序代码,考虑到上面列出的一些限制。如Ahead-of-Time Compilation: AOT Usage 中所述,如果 AOT 库已使用该工具编译为:
jaotc --output libHelloWorld.so HelloWorld.class
它可以在执行阶段使用
java -XX:AOTLibrary=./libHelloWorld.so HelloWorld
提供在编译时和运行时使用相同版本的 JVM 配置。
一旦使用上述命令触发执行,则使用 AOT 编译文件在默认情况下为 ON。为了切换是否使用这些文件,引入了可在执行阶段使用的新参数。IE -
-XX:+/-UseAOT
更重要的是要与上述两个问题相关,甚至在提案的风险和假设部分明确提到:
如果用户发现应用程序启动速度较慢,或者没有达到预期的峰值性能,或者崩溃,他们可以使用
-XX:-UseAOT
标志关闭 AOT,或删除任何 AOT 库。