JEP 243:Java 级别 JVM 编译器接口
概述
开发一个基于 Java 的 JVM 编译器接口(JVMCI),使 JVM 能够将用 Java 编写的编译器作为动态编译器使用。
目标
-
允许针对 JVMCI 编程的 Java 组件在运行时加载,并被 JVM 的编译代理(compile broker)使用。
-
允许针对 JVMCI 编程的 Java 组件在运行时加载,并被受信任的 Java 代码使用,以在 JVM 中安装机器代码,这些代码可以通过对已安装代码的 Java 引用进行调用。
非目标
- 基于 JVMCI 集成一个动态编译器(例如 Graal)。
成功指标
- 基于 JVMCI 的动态编译器在未经修改的 JVM 上运行的能力。编译器及其生成代码的性能并不是重点关注的问题,因为 JVMCI 将作为 JDK 9 中的实验性功能,只有通过在命令行中指定某些标志才会启用。
动机
优化编译器是一种复杂的软件,它极大地受益于 Java 提供的功能,例如自动内存管理、异常处理、同步、出色的(且免费的)IDE、优秀的单元测试支持,以及通过服务加载器实现的运行时可扩展性,仅举几例。此外,编译器不需要许多其他 JVM 子系统(如字节码解释器和垃圾收集器)所需的低级语言特性。这些观察结果强烈表明,在 Java 中编写 JVM 编译器应该能够生成高质量的编译器,并且比现有的用 C 或 C++ 开发的编译器更容易维护和改进。JVMCI 提供了展示和试验这种潜力所需的 API。
描述
JVMCI API 将由以下机制组成:
- 访问优化字节码到机器码编译器所需的虚拟机数据结构,例如类、字段、方法、性能分析信息等。
- 安装编译后的代码以及 JVM 管理编译代码所需的所有元数据,例如垃圾回收(GC)映射和支持去优化的信息。
- 接入 JVM 的编译系统,以处理 JVM 请求,生成方法的机器代码。
Graal 提供了一个极佳的示例,展示了如何利用 JVMCI 在 JVM 中编写并部署高性能编译器。在广泛的基准测试中,Graal 展现了与 C2 相当的峰值性能。
替代方案
对于基于 Java 的编译器,目前尚无可用作 JVM 中动态编译器的现有替代方案。
测试
JVMCI 的实现包括一组广泛的单元测试,这些测试针对暴露给编译器开发者的 API 部分,以及针对内部调用 VM 以实现公共部分的白盒测试。
风险与假设
一个允许访问虚拟机内部并安装和执行编译代码的 Java API 显然存在安全风险。在 JDK 8 中(JVMCI 首次被原型化,并且仍然与 JDK 9 移植版本共同开发),JVMCI API 通过使用一个仅对引导类路径上的代码可访问的类加载器来隐藏,以避免被不受信任的代码访问。在 JDK 9 中,计划利用模块系统 JEP 261 的访问控制功能,防止不受信任的代码使用 JVMCI。JVMCI 需要像 Unsafe
类一样受到严格的安全保护。
JVMCI 在 JDK 9 中将是实验性的功能,因此需要额外的命令行选项来启用它。例如:
-XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -XX:+UseJVMCICompiler -Djvmci.Compiler=<name of compiler>
将 JVMCI 设为实验性功能可以在降低对 JVM 用户的风险的同时,进行广泛的试验。
依赖项
如上所述,JVMCI 依赖于 JEP 261 中的访问控制来隔离 JVMCI 和不受信任的代码。