JSI:什么是JSI、工作原理及架构

作者: IT Sectr 发布日期: 2026-06-04 阅读时间: 10 分钟

JSI(JavaScript Interface)是React Native中的一个软件层,它提供了从JavaScript到C++对象和函数的直接同步访问,取代了异步JSON桥Bridge。与其前身不同,JSI允许在不序列化消息的情况下调用原生方法,并直接将C++对象的引用传递到JS环境中。根据React Native团队(2025)的数据,JSI在密集数据交换的场景中,将JS与原生代码的交互速度提升高达10倍。

要点

  • JSI——JavaScript接口,提供从JS到原生C++代码的同步访问
  • 直接访问消除了序列化为JSON和异步消息队列的需求
  • 性能JS与原生代码的交互提升5–10倍
  • 架构JSI是React Native新架构中Fabric和TurboModules的基础
  • C++集成允许无需原生包装器即可连接任意C++库

什么是JSI?

JSI(JavaScript接口)是一个C++层,它为JavaScript引擎(Hermes、JavaScriptCore、V8)提供直接访问C++对象、函数和内存的能力。与Bridge(将调用序列化为JSON并通过异步队列传输)不同,JSI允许JS代码同步调用C++方法并立即获得结果。

JSI是在React Native 0.64中作为新架构(New Architecture)的一部分引入的。主要目标是消除Bridge这个瓶颈:JS与原生代码之间的每次交互都消耗时间在序列化、反序列化和通过消息队列传输上。JSI通过包装器(实现jsi::Value、jsi::Object和jsi::Function接口)为JS引擎提供对C++对象的直接访问来解决这个问题。

JSI不是Bridge的“一对一”替代品——这是一种根本不同的集成方法。Bridge像一个邮箱一样工作:JS发送一条消息,它经过队列,原生端处理它并发送回复。JSI像一个指针一样工作:JS接收到对C++对象的引用,并可以像普通JS函数一样同步调用其方法。这是两个环境交互架构中的根本区别

创建历史

对JSI的需求源于2015年React Native中原始Bridge的局限性。随着框架的流行度增长和应用程序复杂化,性能问题变得明显:每次原生模块调用至少需要3–5毫秒进行序列化。对于简单的操作,如读取传感器值或获取屏幕尺寸,这是可以接受的,但对于动画、图形处理和流式数据处理来说却是关键问题。React Native团队于2019年开始研究新架构,JSI成为其基础。

JavaScript引擎支持

JSI被设计为JavaScript引擎之上的抽象层。它提供统一的C++ API,针对每个特定引擎实现:Hermes、JavaScriptCore(iOS)、V8(Android)。这意味着开发人员无需担心引擎之间的差异——Fabric和TurboModules无论使用哪种JS引擎都同样工作。

JSI如何工作?

JSI的基础是Host Objects的概念——作为原生JS对象导出到JS环境中的C++对象。当JS代码访问此类对象的属性或方法时,JSI拦截调用并将其委托给相应的C++方法。这是在同一个线程中同步发生的,无需上下文切换,也无需为JSON字符串分配内存。

每个Host Object实现jsi::HostObject接口,包含get、set和getPropertyNames方法。JS引擎每次访问对象属性时都会调用这些方法。例如,在JS中调用NativeModule.someMethod()时,JSI将此调用转换为Host Object相应方法的C++调用。返回值作为jsi::Value传回JS——这是一种通用类型,可以表示数字、字符串、布尔值、对象或undefined。

JSI的一个重要特性是没有消息队列。Bridge使用异步队列:JS发送请求,切换到其他任务,原生端处理请求,结果通过回调返回。JSI同步工作:如果JS通过JSI调用原生模块的方法,JS代码的执行将暂停直到获得结果。这简化了逻辑(无需等待回调)并消除了竞态条件,但需要谨慎——长时间的同步调用会阻塞JS线程。

JSI值的生命周期

通过JSI创建的值存在于JS引擎的运行时环境中,并由垃圾回收器管理。当C++代码创建jsi::String或jsi::Object并将其返回给JS时,环境会自动管理内存。如果C++代码想在调用之间保留对JS值的引用,它会使用jsi::Value::getWeak()或全局jsi::Object::setProperty,在运行时根对象上保留引用。这可以防止垃圾回收器过早删除。

线程安全

JSI默认不是线程安全的。所有JSI方法调用必须来自执行JS的线程(通常是React Native的JS线程)。如果原生模块在单独的线程中启动后台工作,结果必须通过JS线程使用TurboModules中的runOnJS调用返回。这个限制是同步性和缺乏序列化的代价。

JSI与Bridge对比

JSI和Bridge之间的差异具有根本性,影响JS与原生代码交互的所有方面。Bridge是异步的,将数据序列化为JSON并使用消息队列;JSI是同步的,使用原生引用,不需要序列化。

参数BridgeJSI
调用模型异步队列同步直接调用
序列化JSON(序列化+反序列化)无(对C++对象的直接引用)
延迟每次调用3–10毫秒每次调用0.1–0.5毫秒
类型系统动态(通过JSON)静态(通过Codegen)
C++集成仅通过原生模块(Java/ObjC)直接,无需中间层
线程单独的原生线程JS线程(同步)

根据React Native团队的数据,Facebook Marketplace应用从Bridge迁移到JSI后,启动时间减少了35%,内存消耗减少了20%,原因是消除了JS和原生端之间的数据重复。

Bridge何时必要

Bridge不是“错误”——在2015年创建React Native时,这是一个合理的架构决策。为两种不同语言的平台进行原生开发需要一种通用的交换格式。JSON作为序列化格式在所有平台上都可用,并允许统一交互。问题后来才显现出来,当React Native开始用于每秒数千次原生模块调用的复杂应用时。

向后兼容

React Native保持向后兼容:为Bridge编写的原生模块通过兼容层继续在新架构中工作。但对于新模块,建议直接通过TurboModules使用JSI。现有模块的迁移涉及更改交互协议,而不改变模块自身的业务逻辑。

JSI在React Native架构中

JSI是基础层,React Native新架构的所有组件都构建在其上。没有JSI,Fabric(新渲染器)和TurboModules(优化的原生模块)都无法工作。JSI在所有层级上提供JS与C++交互的统一方式。

Fabric与JSI

Fabric——新的React Native渲染器,使用JSI同步访问C++中的UI表示。在旧架构中,渲染通过Bridge进行:JS创建React元素,序列化为JSON,通过Bridge发送,原生端反序列化并创建UI。Fabric通过JSI直接从JS创建C++ Shadow Tree对象,通过Yoga同步计算布局,并将准备好的帧传递给原生渲染器——无需任何序列化。

TurboModules与JSI

TurboModules——React Native原生模块的演进。TurboModules不是将模块注册到Bridge并通过JSON调用其方法,而是使用JSI进行懒加载和直接调用。当JS代码首次访问模块时,JSI创建一个Host Object——它加载原生模块并将其方法作为C++函数提供。懒加载意味着模块在首次使用前不消耗内存——这对于拥有数十个原生模块(其中许多仅在某些屏幕上使用)的应用程序尤其重要。

通过JSI的代码生成

在新架构中使用JSI时,会用到Codegen——一个从JavaScript规范生成C++包装器的工具。开发人员用TypeScript或Flow描述原生模块的接口,Codegen生成实现与JSI兼容的Host Object的C++代码。这自动化了日常工作,并保证了JS和C++端的类型同步。

JSI代码示例

让我们看看实际中如何使用JSI。在这个示例中,创建了一个简单的C++类,通过JSI导出到JS,并从React Native JavaScript代码中调用其方法。

cpp
// Calculator.h — 可从JS访问的C++类头文件
class Calculator {
public:
    double add(double a, double b) { return a + b; }
    double multiply(double a, double b) { return a * b; }
};

Calculator类包含两个算术方法。我们需要使其可从JS访问。为此,我们创建一个Host Object来包装Calculator并通过JSI提供其方法。

cpp
// CalculatorHostObject.cpp — JSI包装器的实现
class CalculatorHostObject : public jsi::HostObject {
private:
    Calculator calc;

public:
    jsi::Value get(jsi::Runtime& runtime,
        const jsi::PropNameID& name) override {
        auto propName = name.utf8(runtime);

        if (propName == "add") {
            return jsi::Function::createFromHostFunction(
                runtime, name, 2,
                [this](jsi::Runtime& runtime,
                    const jsi::Value& thisVal,
                    const jsi::Value* args,
                    size_t count) -> jsi::Value {
                    return jsi::Value(calc.add(
                        args[0].asNumber(),
                        args[1].asNumber()));
                });
        }
        return jsi::Value::undefined();
    }
};

在这段代码中,get方法在每次JS访问对象属性时被调用。如果属性名是“add”,则返回一个C++函数,该函数从JS接收两个参数并调用calc.add()。值作为jsi::Value返回——JSI自动将double转换为JS数字。

从JavaScript调用

在JS环境中注册Host Object后,调用看起来就像普通的JS函数。所有类型在代码生成阶段进行检查,从而消除了运行时的类型不匹配错误。

js
// JavaScript — 通过JSI调用C++计算器
import { Calculator } from 'react-native-calculator'

const result = Calculator.add(5, 3)
console.log(result) // 8 — 同步,无延迟

const product = Calculator.multiply(4, 2.5)
console.log(product) // 10 — 即时结果

注意:结果立即返回,无需Promise、无需await、无需回调。这是一个同步调用,在Bridge架构中是不可能的。对于长时间运行的操作(读取文件、网络请求),应使用异步模式——JSI并不消除对后台线程处理繁重任务的需求。

在实践中,大多数开发人员不手动编写JSI Host Objects——这项工作由Codegen完成,它基于TypeScript规范生成C++包装器。然而,理解JSI在引擎盖下的工作原理对于有效调试性能和创建需要直接访问C++库(Skia、FFmpeg、OpenCV)的复杂原生模块是必要的。

常见问题

JSI与Bridge在React Native中有什么不同?

Bridge通过JSON序列化和消息队列异步工作——每次调用需要3–10毫秒进行数据转换。JSI提供对C++对象的同步直接访问,无需序列化,将延迟降低到0.1–0.5毫秒。JSI还支持传递对象引用,而不是它们的副本。

JSI是否支持所有JavaScript引擎?

是的,JSI提供统一的C++ API,已为Hermes(React Native默认)、JavaScriptCore(iOS)和V8(Android)实现。开发人员无需为不同引擎编写不同代码——Fabric和TurboModules在所有支持的引擎上同样工作。

旧的本地模块能否与JSI一起使用?

是的,React Native提供向后兼容层。为Bridge编写的原生模块继续在新架构中工作。但建议将它们迁移到TurboModules以获得JSI的优势——懒加载和同步调用。

JSI是否需要C++知识?

对于日常开发——不需要。原生模块的TypeScript规范通过Codegen自动编译为C++包装器。只有在创建自己的C++库或在运行时级别调试JSI性能时才需要C++知识。

JSI解决了哪些问题?

JSI解决了Bridge的三个关键问题:由于JSON序列化导致的高延迟、缺乏同步调用以及无法通过引用传递复杂对象。JSI还允许直接集成C++库,无需Java或Objective-C层。

总结

  • JSI(JavaScript接口)——React Native中从JavaScript直接同步访问C++对象的技术
  • 架构JSI基于Host Objects——作为原生JS对象导出到JS的C++对象
  • 性能通过JSI的调用由于没有序列化,比通过Bridge高10–50倍
  • Fabric和TurboModules——构建在JSI之上的React Native新架构的关键组件
  • 同步性JSI简化了代码逻辑,但在长时间操作时需要谨慎
  • C++集成允许无需平台包装器即可连接任意原生库
  • 使用JSI用于高性能原生模块,并将现有Bridge模块迁移过来

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读