什么是 JNI?Java 原生接口详解

JNI(Java Native Interface)是连接器,它允许 Java 代码调用本地的 C 或 C++ 函数,并允许本地代码回调到 JVM.

Conceptsby trqUpdated June 4, 2026
Key takeaways
  • JNI 是内置接口,允许 JVM 代码调用本地的 C 或 C++ 函数,并允许本地代码回调到 Java。
  • native 方法没有 Java 代码体;JVM 在运行时将其链接到编译后的函数。
  • 程序利用它来重用本地库,访问操作系统,加速热点路径,或直接操作硬件。
  • 边界非常清晰:本地崩溃可能导致 JVM 崩溃,而本地构建是平台特定的.

JNI 是 Java 原生接口,它是 Java 内置的一部分,允许在 JVM 上运行的代码调用用 C 或 C++ 编写的函数,并允许这些原生代码反过来调用 Java 代码。 这就是 Java 程序如何通过 JVM 使用平台库或编译后的机器代码片段.

Opal 的适配

Opal 是一个 Fabric 模组,因此大部分内容都是纯 Java,您可以使用 JavaScript 编写脚本,而无需接触原生代码。 如果您刚开始使用,请参阅 设置指南

JNI 的作用

JNI 连接两个世界:JVM 上的托管 Java 代码和编译为机器指令的本地代码。一个 Java 方法被标记为 native,在 Java 中没有主体。运行时,JVM 加载一个本地库并将该方法链接到匹配的 C 或 C++ 函数。从那里,两端相互传递参数和返回值。

本地端获得一个 JNIEnv 指针。这个句柄是门户:它暴露了读取 Java 字段、调用 Java 方法、创建对象和抛出异常的函数。因此,桥梁是双向运行的,而不仅仅是 Java 伸出援手。

为什么程序使用它

大多数 Java 代码不需要 JNI。程序在以下几种情况下使用它:

  • 重用现有的本地代码。 一个成熟的 C 或 C++ 库已经完成了这项工作,用 Java 重新编写它并不值得。
  • 访问操作系统。 一些平台功能没有纯 Java API,因此本地调用是唯一的途径。
  • 加速热点路径。 一个紧密的数值或底层例程可以作为编译后的本地代码运行得比在 JVM 上更快。
  • 接触硬件或驱动程序。 图形、音频和设备访问通常隐藏在本地库之后。

JNI 调用是如何工作的

步骤在每个平台上都是相同的.

步骤发生的情况
声明Java 方法使用 native 关键字编写,且没有方法体。
构建C 或 C++ 函数被编译成共享库 (.dll, .so, .dylib)。
加载Java 在运行时调用 System.loadLibrary 加载该库。
链接JVM 通过名称将 native 方法与 C 函数匹配。
调用Java 调用该方法;控制权交由原生代码,再返回。

函数名称遵循固定的模式,以便 JVM 能够找到它们,生成的头文件会告诉你需要实现的精确签名。

成本与风险

JNI 功能强大,但也存在潜在风险。原生代码中的崩溃可能会导致整个 JVM 崩溃,因为该代码运行在 JVM 安全机制之外。原生侧分配的内存不会被垃圾回收,因此容易出现内存泄漏。Java 和原生代码之间的每一次跨越都有开销,因此在循环中频繁跨越边界可能会导致性能下降。而且原生库是平台特定的:为 Windows 构建的库无法在 Linux 上运行,除非单独编译.

谨慎使用

由于原生边界绕过了 JVM 的安全保障,JNI 只能作为没有纯 Java 解决方案时的选择。大多数模组,包括 Opal,都无需使用它。

常见问题