0Pricing
Java Academy · 课时

为什么选择 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 反馈 — 无需本地设置。

此课程中的所有课时

  1. 为什么选择 FFM 而不是 JNI
  2. MemorySegment 与 Arena
  3. 下调用句柄
  4. 布局与结构体
← 返回 Java Academy