Jeandle JDK 或:为何开发者将 LLVM 嫁接到 Java 虚拟机上
深入 HotSpot JVM 的 C2 编译器核心并非易事。C2 的 C++ 代码历经数十年编写,积累了大量的特定优化,但维护难度逐年递增。Oracle 的工程团队曾尝试通过 Graal 项目简化这一过程,用 Java 重写 JIT 编译器。而 Jeandle 项目的开发者则另辟蹊径:他们决定以现有 LLVM 框架为基础,将其作为 OpenJDK 的编译引擎。

什么是 Jeandle 以及为何需要 LLVM
Jeandle 是一个基于 OpenJDK 直接构建的实验性 JIT 编译器。它不依赖内置的 C1 或 C2 编译器,而是拦截热点字节码的执行并将其传递给 LLVM 的代码生成器。
为什么要将 LLVM 引入 Java 虚拟机?
LLVM 的主要优势在于全球社区为 C、C++ 和 Rust 开发的海量底层优化集合。自动指令向量化、深度循环分析以及针对特定处理器特性的优化,这些都已在 LLVM 中存在并持续更新。
在传统的 C2 中,每个新优化或对新处理器架构(如 RISC-V)的支持都必须手动实现。通过将 OpenJDK 与 LLVM 结合,Jeandle 的作者希望获得一个强大的机器码生成器,而无需从头重写优化器。
底层工作原理
Jeandle 中的代码处理分为多个阶段:
- 虚拟机追踪频繁调用的应用方法。
- 当方法的字节码被判定为热点时,Jeandle 将其转换为 LLVM IR。
- LLVM 的优化通道被应用于生成的 IR 代码。
- LLVM 将 IR 编译为目标平台(x86_64、AArch64 等)的原生机器码。
- JVM 替换方法引用,继续执行编译后的机器码。
项目仓库包含详尽的文档。guides 目录中有系统架构描述、构建说明以及单独的调试配置文档。
开发者通过专用 JVM 标志暴露编译器行为控制。这些标志允许在应用运行时调整优化级别并请求 LLVM IR 中间表示转储。
基于 LLVM 的 JIT 所面临的主要挑战
在 JIT 编译器中使用 LLVM 的想法并不新鲜。早期在 OpenJDK 的 Shark 项目和 Azul 的 Falcon 项目中都做过类似尝试。这条路上的主要障碍是编译速度本身。
LLVM 最初是为提前编译(AOT)设计的。在像 Clang 这样的静态编译器中,编译过程可能需要数分钟——重点是最终二进制文件运行得尽可能快。而在 JIT 模式下,编译时间至关重要。如果 LLVM 开始花费很长时间精细优化每个方法,应用在预热阶段就会直接冻结。
此外,Jeandle 的作者还面临与 Java 运行时集成的复杂任务。编译器需要正确处理垃圾回收器的安全点、处理内存屏障,并支持动态类加载。
当前状态与未来展望
目前,Jeandle 处于积极的原型设计阶段。仓库已积累约 460 个 star 和超过 60 个开放 issue。代码尚未准备好用于生产环境,作者们也并未隐瞒这一点。
尽管如此,该项目将引起以下几类工程师的兴趣:
- 正在学习 JVM 内部机制并想通过实际案例理解 JIT 工作原理的人。
- 寻找实际 LLVM IR 集成用例的编译器开发者。
- 为特定处理器架构创建自定义优化配置的研究人员。
源代码以 GPL v2.0 许可证开源。如果您想了解如何将 Java 虚拟机与原生编译器结合,请查阅项目文档——其中详细介绍了构建过程和架构决策。
相关项目