基于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 任务调度 |