JSI、NAPI、JNI、ArkTS Native 到底是什么关系
这四个词都出现在「JavaScript 怎么调到底层」这条链路上,但它们不在同一层,也不能互相替换。混用时,问题通常不是语法,而是找错了边界。
JNI 最早、也最窄。它是 JVM 的官方 C 接口:Java / Kotlin 调 C/C++,或反过来。Android 上几乎所有「Native 库」最后都要过 JNI。它不认识 JavaScript,也不认识 ArkTS。有人说「JS 调了 Native」,在安卓上往往只是故事的后半段:前面还有别的桥,最后才落到 JNI。
JSI 是 React Native 新架构里的 JS 引擎接口。它面对的是 Hermes、JSC、V8 这类引擎,把 C++ 对象(HostObject)直接挂到 JS 运行时上,可以同步调用,不必再走旧 Bridge 的 JSON 队列。JSI 解决的是 JS ↔ C++。若 C++ 后面还要碰 Android Java,仍然要再走 JNI。所以一条完整路径经常是:JS → JSI → C++ → JNI → Java。JSI 替代的是 RN 的消息桥,不是 JNI。
NAPI 来自 Node 的稳定 ABI,后来被 OpenHarmony 用来做 JS/ArkTS 调 C/C++。思路和 JSI 很像:在 C 里注册方法,运行时变成 JS 对象上的函数。差别在生态和头文件。NAPI 是一套 C ABI,版本承诺相对稳,适合系统组件和三方 .so;JSI 是 C++ API,和 RN Runtime、TurboModule、Fabric 绑在一起。OpenHarmony 应用里写 Native 模块,默认文档是 NAPI,不是 JSI。只有在 OH 上跑 React Native、或自研引擎绑定时,才会碰到 JSI。
ArkTS Native 不是第四套独立 ABI,而是鸿蒙侧的说法:用 ArkTS 写业务,把重活、硬件、已有 C/C++ 库放到 Native。落地接口主要是 NAPI(再往下才是系统 so、驱动、厂商 SDK)。ArkTS 负责类型、并发和 UI;NAPI 负责把 C 函数变成 import { foo } from 'libxxx.so'。它不经过 JNI,因为鸿蒙应用主语言不是 JVM。
可以记一张分层图:
• 语言层:ArkTS / JS / Java / Kotlin
• 引擎绑定层:JSI(RN 引擎)或 NAPI(Node / OpenHarmony)
• 系统互操作层:JNI(仅 JVM)
• 实现层:C/C++ 库、系统 API
关系不是「四个并列方案选一个」,而是:
1. 在 React Native 里加速 JS 调 C++,用 JSI;到了 Android Java,再接 JNI。
2. 在 OpenHarmony / ArkTS 里扩展 Native,用 NAPI;不要去套 RN 的 JSI 头文件。
3. JNI 只出现在「必须进 JVM」的时候;纯 OH 应用链路里通常没有它。
4. ArkTS Native 描述的是分工(TS 业务 + C++ 能力),NAPI 才是那根电线。
选型时先问运行在哪。RN 新架构 → JSI;鸿蒙 ArkTS 模块 → NAPI;Android Java 调 so → JNI。三者可以在同一个 App 里同时存在(例如 OH 上的 RN:ArkTS 壳 + JSI 模块 + 若再嵌 Android 才出现 JNI),但每一跳的职责必须分开。否则就会出现「用 JNI 的思路写 NAPI」或「以为 JSI 能直接调 Java」这类错层问题。
一句话:JSI 连 JS 引擎和 C++,NAPI 连 ArkTS/JS 和 C++,JNI 连 JVM 和 C++,ArkTS Native 是鸿蒙上「用 NAPI 接 C++」这种架构的名字,不是另一套协议。
更多推荐
所有评论(0)