为什么选择 FFM 而不是 JNI
更安全的原生互操作
为什么选择 FFM 而不是 JNI 是 CoddyKit 上的免费 Java Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Java Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Java Academy 课程共包含 4 节课。
调用本机代码
Java 有时需要调用 C 语言库或处理堆外内存。传统方式是使用Java 原生接口(JNI)。现代方式是外部函数与内存 API(FFM),该 API 已在 Java 22 中正式定型(JEP 454)。
本课将解释为什么 FFM 是更好的选择。
JNI 的要求
JNI 使用起来很繁琐:
- 使用笨拙的
JNIEXPORT签名编写 C 语言胶水代码 - 为每个平台分别编译本机共享库
- 手动转换 Java 类型和 C 语言类型
- 稍有错误就很容易导致 JVM 崩溃
FFM 完全使用 Java
FFM 让您能够完全通过 Java调用本机函数并访问本机内存。不需要 C 语言胶水代码,不需要单独的编译步骤,也不需要手写编组代码。
您可以在 Java 中描述本机函数的签名,并通过方法句柄调用它。
核心包
所有内容都位于 java.lang.foreign 中。主要类型包括:
- 使用
Linker和SymbolLookup查找并绑定函数 - 使用
MemorySegment表示本机内存 - 使用
Arena管理确定性的生存期 - 使用
MemoryLayout和FunctionDescriptor描述数据形状
通过设计实现更高安全性
FFM 比 JNI 安全得多:
- 访问内存时进行边界检查
- 生命周期与一个
Arena绑定,因此会捕获释放后使用的情况 - 隔离可防止不安全的跨线程访问
发生错误时会抛出 Java 异常,而不是导致 VM 崩溃。
API 初体验
这个示例会查找 C 函数 strlen,并准备好一个指向它的句柄。重点在于:这一切都只是普通的 Java 代码。
import java.lang.foreign.*;
import java.lang.invoke.MethodHandle;
public class Main {
public static void main(String[] args) {
Linker linker = Linker.nativeLinker();
SymbolLookup stdlib = linker.defaultLookup();
MethodHandle strlen = linker.downcallHandle(
stdlib.find("strlen").orElseThrow(),
FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.ADDRESS));
System.out.println("Bound a handle to strlen: " + strlen);
}
}性能
FFM 下调用的性能可与 JNI 相媲美,而且通常更快,因为 JIT 可以对生成的存根进行内联和优化。不需要在每次调用时跨越 C 中转跳板。
启用本地访问
由于本地代码可能很危险,FFM 可能会发出警告,或要求您主动启用访问权限。您可以在启动时通过 --enable-native-access=ALL-UNNAMED(或指定的模块名称)授予访问权限,从而消除警告。
替代 sun.misc.Unsafe
FFM(结合内存 API)也是官方认可的替代方案,用于取代长期弃用的 sun.misc.Unsafe 堆外操作。过去需要手动管理本地缓冲区的库,可以迁移到安全且受支持的 API。
工具:jextract
对于大型 C 库,配套工具 jextract 会读取 C 头文件,并自动生成 Java FFM 绑定。您无需再手动编写描述符。
它是 FFM 在生产力方面的补充,就像代码生成器一样。
何时使用 FFM
在必须完成以下任务时,请使用 FFM:
- 调用现有的 C/C++ 库
- 在较低层级与 OS 交互
- 高效管理大型堆外缓冲区
对于纯 Java 工作,您完全不需要它。
快速检查
回想一下 FFM 相比 JNI 的主要优势。
总结
您已经了解了 FFM 为什么胜过 JNI:
- 纯 Java,无需 C 胶水代码或额外编译
- 安全:提供边界检查、Arena 生命周期管理和隔离
- 性能可与 JNI 相媲美,甚至更好
- 替代
sun.misc.Unsafe,并可与jextract配合使用
下一步:使用 MemorySegment 和 Arena 管理本地内存。
常见问题解答
「为什么选择 FFM 而不是 JNI」课时是免费的吗?
是的 — 「为什么选择 FFM 而不是 JNI」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Java Academy 课程的其余内容,请升级到 CoddyKit PRO。 Java Academy 课程共包含 4 节课。
「为什么选择 FFM 而不是 JNI」这节课中我会学到什么?
更安全的原生互操作 你通过在浏览器中直接运行的动手代码来练习 Java Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Java Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Java Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。
「为什么选择 FFM 而不是 JNI」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Java Academy 课中编写并运行代码吗?
能。每节 Java Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 为什么选择 FFM 而不是 JNI
- MemorySegment 与 Arena
- 下调用句柄
- 布局与结构体