React Native 源码分析1——HybridData 机制深度分析

基于RN0.77 源码

一、HybridData 是什么

HybridData 来自 Facebook 的 fbjni 库(com.facebook.jni.HybridData),它是一个将 C++ 对象指针封装在 Java 对象中的桥梁类。本质上是 Java 层持有 C++ 层对象的"句柄",实现了 Java 和 C++ 之间一对一的对象绑定。

二、内存管理流程

scss 复制代码
┌─────────────────────────────────────────────────┐
│  Java 层                                         │
│  ┌──────────────────────────────┐                │
│  │ HermesExecutor         │                │
│  │  mHybridData ──────────────────┐              │
│  └──────────────────────────────┘ │              │
│                                   ▼              │
│  ┌──────────────────────────────┐                │
│  │ HybridData (fbjni)          │                │
│  │  内部持有 C++ 指针 (long)    │                │
│  └──────────────────────────────┘                │
└─────────────────────────────────────────────────┘
                │ JNI
                ▼
┌─────────────────────────────────────────────────┐
│  C++ 层                                         │
│  ┌──────────────────────────────┐                │
│  │ HermesExecutorHolder (C++)   │                │
│  │                              │                │
│  │                              │                │
│  └──────────────────────────────┘                │
└─────────────────────────────────────────────────┘

二、核心工作原理

java 复制代码
public class HermesExecutor extends JavaScriptExecutor {
  private static String mode_ ;

  static {
    loadLibrary();
  }

  public static void loadLibrary() throws UnsatisfiedLinkError {
    if (mode_ == null) {
      // libhermes must be loaded explicitly to invoke its JNI_OnLoad.
      SoLoader.loadLibrary( "hermes" );
      SoLoader.loadLibrary( "hermes_executor" );
      // libhermes_executor is built differently for Debug & Release so we load the proper mode.
      mode_ = ReactBuildConfig.DEBUG ? "Debug" : "Release" ;
    }
  }

  HermesExecutor(@Nullable RuntimeConfig config, boolean enableDebugger, String debuggerName) {
    super(
        config == null
            ? initHybridDefaultConfig(enableDebugger, debuggerName)
            : initHybrid(enableDebugger, debuggerName, config.getHeapSizeMB()));
  }

  @Override
  public String getName() {
    return "HermesExecutor" + mode_ ;
  }

  private static native HybridData initHybridDefaultConfig(
      boolean enableDebugger, String debuggerName);

  private static native HybridData initHybrid(
      boolean enableDebugger, String debuggerName, long heapSizeMB);
}

HermesExecutor继承JavaScriptExecutor,JavaScriptExecutor中定义了一个mHybridData字段

arduino 复制代码
private final HybridData mHybridData;

HermesExecutor构造函数调用initHybridDefaultConfig或initHybrid返回一个HybridData对象,initHybridDefaultConfig和initHybrid都是native方法;

在OnLoad.cpp中注册了这两个方法,并且这两个方法都是HermesExecutorHolder类中

scss 复制代码
static void registerNatives() {
  registerHybrid(
      {makeNativeMethod( "initHybrid" , HermesExecutorHolder::initHybrid),
       makeNativeMethod(
           "initHybridDefaultConfig" ,
           HermesExecutorHolder::initHybridDefaultConfig)});
}

initHybrid中会创建HermesExecutorFactory对象,然后调用makeCxxInstance,它是实现了 Java 和 C++ 之间一对一的对象绑定的关键

rust 复制代码
static jni::local_ref<jhybriddata> initHybrid(
    jni::alias_ref<jclass>,
    bool enableDebugger,
    std::string debuggerName,
    jlong heapSizeMB) {
  JReactMarker::setLogPerfMarkerIfNeeded();
  auto runtimeConfig = makeRuntimeConfig(heapSizeMB);
  std::call_once(flag, []() {
    facebook::hermes::HermesRuntime::setFatalHandler(hermesFatalHandler);
  });
  auto factory = std::make_unique<HermesExecutorFactory>(
      installBindings, JSIExecutor::defaultTimeoutInvoker, runtimeConfig);
  factory->setEnableDebugger(enableDebugger);
  if (!debuggerName.empty()) {
    factory->setDebuggerName(debuggerName);
  }
  return makeCxxInstance(std::move(factory));
}

makeCxxInstance中会创建T对象,在这个案例中T为C++层的HermesExecutorHolder(OnLoad.cpp)

c 复制代码
static local_ref<detail::HybridData> makeCxxInstance(Args&&... args) {
  return makeHybridData(
      std::unique_ptr<T>(new T(std::forward<Args>(args)...)));
}

makeHybridData中创建了一个HybridData对象并返回到Java层

c 复制代码
static local_ref<detail::HybridData> makeHybridData(
    std::unique_ptr<T> cxxPart) {
  auto hybridData = detail::HybridData::create();
  setNativePointer(hybridData, std::move(cxxPart));
  return hybridData;
}

setNativePointer中t是HybridData对象,new_value是HermesExecutorHolder对象

scss 复制代码
void setNativePointer(
    basic_strong_ref<T, Alloc> t,
    std::unique_ptr<detail::BaseHybridClass> new_value) {
  getHolder(&*t)->setNativePointer(std::move(new_value));
}

看完getHolder就明白了,它是取出HybridData对象中的mDestructor字段

rust 复制代码
local_ref<HybridDestructor::javaobject> getHolder(const T* t) {
  static auto holderField = getDestructorField(t->getClass());
  return t->getFieldValue(holderField);
}

inline JField<HybridDestructor::javaobject> getDestructorField(
    const local_ref<JClass>& c) {
  return c->template getField<HybridDestructor::javaobject>( "mDestructor" );
}

setNativePointer最终会将mDestructor.mNativePointer指向HermesExecutorHolder对象

scss 复制代码
getHolder(&*t)->setNativePointer(std::move(new_value));
变成
HybridDestructor->setNativePointer(std::move(new_value));


//fbjni-0.7.0/prefab/modules/fbjni/include/fbjni/fbjni.cpp:227-237
void HybridDestructor::setNativePointer(
    std::unique_ptr<detail::BaseHybridClass> new_value) {
  static auto pointerField =
      javaClassStatic()->getField<jlong>("mNativePointer");
  auto old_value = std::unique_ptr<detail::BaseHybridClass>(
      reinterpret_cast<detail::BaseHybridClass*>(getFieldValue(pointerField)));
  if (new_value && old_value) {
    FBJNI_LOGF("Attempt to set C++ native pointer twice");
  }
  setFieldValue(pointerField, reinterpret_cast<jlong>(new_value.release()));
}

这就是"Java 对象 -> native 指针 -> C++ 实例"的回路。

scss 复制代码
HermesExecutor (Java++对象) ->HybridData->mDestructor.mNativePointer(指针)->HermesExecutorHolder(C++对象) 

四、在 RN 中的应用场景

HybridData 在 React Native 中无处不在,覆盖了几乎所有核心子系统:

子系统 Java 类 C++ 对应 作用
旧架构 Bridge CatalystInstanceImpl CatalystInstanceImpl.cpp → Instance JS 桥的核心实例
新架构 Bridgeless ReactInstance JReactInstance.cpp → ReactInstance 新架构的运行时实例
JS 引擎 HermesExecutor / JSCExecutor 对应的 C++ executor JS 执行引擎
JS Runtime HermesInstance / JSCInstance C++ runtime factory 创建和管理 JS 运行时
数据类型 WritableNativeMap / WritableNativeArray C++ dynamic 对象 JS 与 Java 间的数据传递
TurboModule TurboModuleManager C++ TurboModule 管理 新架构的模块系统
Fabric 渲染 ComponentFactory C++ 组件注册表 新架构的渲染系统
运行时工具 RuntimeExecutor / RuntimeScheduler C++ executor/scheduler JS 任务调度
相关推荐
机智的张尼玛14 小时前
我基于 Kotlin Multiplatform 实现了一套跨平台的弱网离线同步引擎
android·开源·kotlin
安卓修改大师16 小时前
安卓修改大师反编译引擎Apktool深度解析:版本选择、参数说明与实战技巧
android
error:(17 小时前
【系统与实战双精通】VS Code 调试 ROS2 Python 节点与 Launch 系统指南
android·java·python
黄林晴19 小时前
Kuikly 是什么?和KMP有什么关系?
android·前端
帅次19 小时前
Android 高级工程师面试:Kotlin 语法基础 近1年高频追问 22 题
android·面试·kotlin·扩展函数·空安全
想你依然心痛20 小时前
嵌入式日志系统:分级日志、环形缓冲区与远程输出——运行时调试、非侵入
android·前端·javascript
用户693717500138421 小时前
AI Agent 里的 Loop 到底是什么?
android·前端·后端
海天鹰1 天前
安卓分割空字符串数组长度为1
android
Coffeeee1 天前
从 Android 15 到 Android 17,谷歌猝不及防的音频改动
android·前端·google
用户69371750013841 天前
AI 领域的 Harness,到底是什么意思?
android·前端·后端