文章摘要
这篇文章介绍了如何利用Java的FFM API调用LLVM C接口,通过生成LLVM IR中间语言来创建并即时编译一个打印"Hello, World!"的本地程序,展示了Java与底层编译器技术的结合应用。
文章总结
Java与LLVM的"Hello World"之旅:用Java生成并执行LLVM IR
项目背景
本文是JVM Advent系列的最新篇章,作者James Hamilton(Diffblue高级软件工程师)展示了一个创新方案:使用Java的FFM(Foreign Function & Memory)API调用LLVM C API,生成并执行LLVM IR代码,最终实现经典的"Hello World"程序。
技术亮点
核心工具链:
- 使用LLVM 20.0.0作为编译器基础设施
- 通过Java 22的FFM API实现原生代码调用
- 借助jextract工具自动生成LLVM C API的Java绑定
实现步骤:
- 创建LLVM模块容器
- 定义main函数和基本块
- 构建全局字符串常量"Hello, World!"
- 声明并调用libc的puts函数
- 支持两种执行方式:
- 通过LLVM解释器lli执行IR
- 使用JIT编译器生成原生机器码
关键代码片段:
java // 创建LLVM模块 var module = LLVMModuleCreateWithName(arena.allocateFrom("hello")); // 构建全局字符串 var helloStr = LLVMBuildGlobalStringPtr(builder, arena.allocateFrom("Hello, World!"), arena.allocateFrom("hello_str")); // JIT编译执行 var functionHandle = Linker.nativeLinker().downcallHandle( addressOfMainFunc, FunctionDescriptor.of(JAVA_INT));
环境配置
- 在Ubuntu/Debian安装LLVM 20:
bash wget https://apt.llvm.org/llvm.sh chmod +x llvm.sh ./llvm.sh 20 - Maven项目需配置Java 22+:
xml <properties> <maven.compiler.source>25</maven.compiler.source> <maven.compiler.target>25</maven.compiler.target> </properties>
进阶功能
JIT编译:
- 初始化x86目标平台
- 创建JIT编译器实例
- 通过MethodHandle直接调用编译后的原生函数
内存管理:
- 使用Arena管理原生内存生命周期
- MemorySegment实现安全的内存访问
- try-with-resources确保资源释放
成果展示
最终程序既可通过解释器执行:
bash
java -cp target/*.jar com.example.App | lli
也能通过JIT直接运行:
bash
java -cp target/*.jar com.example.App
均输出:Hello, World!
扩展建议
作者鼓励读者尝试: - 添加更多IR指令 - 实现简单计算功能 - 构建更复杂的LLVM程序
完整代码已开源在GitHub仓库。
本文展示了Java与原生代码交互的新范式,通过FFM API和LLVM的结合,开发者可以在Java生态中实现高性能的原生代码编译和执行能力。
评论总结
评论总结:
- LLVM IR的实用性与趣味性
- 认为LLVM IR适合多种编程语言,且具有教育意义和实用价值 "LLVM IR is quite fun to play with from many programming languages" (jakozaur) "LLVM is such an amazing piece of software...especially when it comes to obfuscation" (kachapopopow)
- 编译器开发实践
- 开发者分享编译器开发经验,寻求标准化AST实现 "constantly revising my AST implementation...searching for standardized AST" (Octoth0rpe)
- 提供编译器开发参考资源 "put together this reference/example before+after...useful to have concise compilation examples" (rendaw)
- 技术安全担忧
- 对直接执行下载脚本的安全风险表示担忧 "shocked how casual people wget and execute shell scripts...equivalent to giving RCE" (tuhgdetzhh)
- Java生态发展
- 对标准JDK使用的疑问 "What's wrong with using the standard JDK for Java code?" (zkmon)
- 关注Java新特性 "Nice read up of the new FFM API...interesting time to be in Java/JVM ecosystem" (mands)
- 其他技术分享
- 多语言Hello World示例 "made a poster showing Hello World in 39 different languages" (troymc)
- 技术链接失效报告 "500 internal server error" (znpy)