ReactNative 源码分析1——HybridData 机制深度分析

55 阅读3分钟

基于RN0.77 源码

ReactNative 源码分析1——HybridData 机制深度分析

ReactNative 源码分析2——Application初始化

ReactNative 源码分析3——ReactActivity之初始化RN应用

ReactNative 源码分析4——ReactActivity之加载JSBundle

ReactNative 源码分析5——ReactActivity之启动RN应用

ReactNative 源码分析6——Native Modules通信机制

ReactNative 源码分析7——Native Modules通信机制 之Js调用Java

ReactNative 源码分析8——Native Modules通信机制 之Java调用Js

ReactNative 源码分析9——Native View初始化

ReactNative 源码分析10——Native View创建流程createView

ReactNative 源码分析11——Native View创建流程setChildren和manageChildren

ReactNative 源码分析12——Native View创建流程onBatchComplete

一、HybridData 是什么

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

二、内存管理流程

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

二、核心工作原理

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字段

private final HybridData mHybridData;

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

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

static void registerNatives() {
  registerHybrid(
      {makeNativeMethod( "initHybrid" , HermesExecutorHolder::initHybrid),
       makeNativeMethod(
           "initHybridDefaultConfig" ,
           HermesExecutorHolder::initHybridDefaultConfig)});
}

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

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)

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

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

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对象

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字段

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对象

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++ 实例”的回路。

HermesExecutor (Java++对象) ->HybridData->mDestructor.mNativePointer(指针)->HermesExecutorHolder(C++对象) 

四、在 RN 中的应用场景

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

子系统Java 类C++ 对应作用
旧架构 BridgeCatalystInstanceImplCatalystInstanceImpl.cpp → InstanceJS 桥的核心实例
新架构 BridgelessReactInstanceJReactInstance.cpp → ReactInstance新架构的运行时实例
JS 引擎HermesExecutor / JSCExecutor对应的 C++ executorJS 执行引擎
JS RuntimeHermesInstance / JSCInstanceC++ runtime factory创建和管理 JS 运行时
数据类型WritableNativeMap / WritableNativeArrayC++ dynamic 对象JS 与 Java 间的数据传递
TurboModuleTurboModuleManagerC++ TurboModule 管理新架构的模块系统
Fabric 渲染ComponentFactoryC++ 组件注册表新架构的渲染系统
运行时工具RuntimeExecutor / RuntimeSchedulerC++ executor/schedulerJS 任务调度