对于想学习Agent开发的朋友可以关注我的新项目:
HelloAgentR工程手记1/100天——项目工作流搭建
一、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++ 对应 | 作用 |
|---|---|---|---|
| 旧架构 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 任务调度 |