react-native js与java通讯过程 (未完)

191 阅读6分钟

1.JS调用java模块中的方法

1.1 分析java模块

以官方案例为例

import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport';  
import {TurboModuleRegistry} from 'react-native';  
  
export interface Spec extends TurboModule {  
add(a: number, b: number): Promise<number>;  
}  
  
export default TurboModuleRegistry.get<Spec>(  
'RTNCalculator',  
) as Spec | null;

首先必须访问NativeModules模块

Libraries\BatchedBridge\NativeModules.js

let NativeModules: {[moduleName: string]: $FlowFixMe, ...} = {};
if (global.nativeModuleProxy) {
  NativeModules = global.nativeModuleProxy;
} else if (!global.nativeExtensions) {
  // ...
}

module.exports = NativeModules;

模块返回的是一个全局的对象nativeModuleProxy,定位到JSIExecutor.cpp中

ReactCommon\jsiexecutor\jsireact\JSIExecutor.cpp

void JSIExecutor::initializeRuntime() {
  // ...
  runtime_->global().setProperty(
      *runtime_,
      "nativeModuleProxy",
      Object::createFromHostObject(
          *runtime_, std::make_shared<NativeModuleProxy>(nativeModules_)));
  // ...
}

发现cpp通过jsi提供的方法setProperty往js运行时全局注入了NativeModuleProxy类型的对象

class JSIExecutor::NativeModuleProxy : public jsi::HostObject {
 public:
  NativeModuleProxy(std::shared_ptr<JSINativeModules> nativeModules)
      : weakNativeModules_(nativeModules) {}

  Value get(Runtime& rt, const PropNameID& name) override {
    if (name.utf8(rt) == "name") {
      return jsi::String::createFromAscii(rt, "NativeModules");
    }

    auto nativeModules = weakNativeModules_.lock();
    if (!nativeModules) {
      return nullptr;
    }

    return nativeModules->getModule(rt, name);
  }

  void set(Runtime&, const PropNameID&, const Value&) override {
    throw std::runtime_error(
        "Unable to put on NativeModules: Operation unsupported");
  }

 private:
  std::weak_ptr<JSINativeModules> weakNativeModules_;
};

发现NativeModuleProxy最终调用了入参nativeModules即为JSINativeModules类型对象的getModule方法,记住这里

JSIExecutor::JSIExecutor(
    std::shared_ptr<jsi::Runtime> runtime,
    std::shared_ptr<ExecutorDelegate> delegate,
    const JSIScopedTimeoutInvoker& scopedTimeoutInvoker,
    RuntimeInstaller runtimeInstaller)
    : runtime_(runtime),
      delegate_(delegate),
      // 此处构建nativeModules delegate对象反推
      nativeModules_(std::make_shared<JSINativeModules>(
          delegate ? delegate->getModuleRegistry() : nullptr)),
      moduleRegistry_(delegate ? delegate->getModuleRegistry() : nullptr),
      scopedTimeoutInvoker_(scopedTimeoutInvoker),
      runtimeInstaller_(runtimeInstaller) {
  runtime_->global().setProperty(
      *runtime, "__jsiExecutorDescription", runtime->description());
}

找到入参对象nativeModules_的构造方法接收一个ModuleRegistry类型的参数delegate->getModuleRegistry(),开始反推delegate对象的获取

直接上调用堆栈:

  • ReactCommon\jsiexecutor\jsireact\JSIExecutor.cpp --- JSIExecutor::JSIExecutor
  • ReactAndroid\src\main\jni\react\jscexecutor\OnLoad.cpp --- JSExecutorFactory::createJSExecutor
  • ReactCommon\cxxreact\NativeToJsBridge.cpp --- NativeToJsBridge::NativeToJsBridge
  • ReactCommon\cxxreact\Instance.cpp --- Instance::initializeBridge
  • ReactAndroid\src\main\jni\react\jni\CatalystInstanceImpl.cpp --- CatalystInstanceImpl::initializeBridge
  • CatalystInstanceImpl.java --- CatalystInstanceImpl::initializeBridge
// ReactCommon\cxxreact\NativeToJsBridge.cpp
NativeToJsBridge::NativeToJsBridge(
    JSExecutorFactory* jsExecutorFactory,
    std::shared_ptr<ModuleRegistry> registry,
    std::shared_ptr<MessageQueueThread> jsQueue,
    std::shared_ptr<InstanceCallback> callback)
    : m_destroyed(std::make_shared<bool>(false)),
      // 此处得到delegate对象
      m_delegate(std::make_shared<JsToNativeBridge>(registry, callback)),
      m_executor(jsExecutorFactory->createJSExecutor(m_delegate, jsQueue)),
      m_executorMessageQueueThread(std::move(jsQueue)),
      m_inspectable(m_executor->isInspectable()) {}
      
class JsToNativeBridge : public react::ExecutorDelegate {
 public:
  JsToNativeBridge(
      std::shared_ptr<ModuleRegistry> registry,
      std::shared_ptr<InstanceCallback> callback)
      : m_registry(registry), m_callback(callback) {}

  // 此处返回注册的模块
  std::shared_ptr<ModuleRegistry> getModuleRegistry() override {
    return m_registry;
  }
  //...
};
// ReactCommon\cxxreact\Instance.cpp
void Instance::initializeBridge(
    std::unique_ptr<InstanceCallback> callback,
    std::shared_ptr<JSExecutorFactory> jsef,
    std::shared_ptr<MessageQueueThread> jsQueue,
    std::shared_ptr<ModuleRegistry> moduleRegistry) {
  callback_ = std::move(callback);
  moduleRegistry_ = std::move(moduleRegistry);
  jsQueue->runOnQueueSync([this, &jsef, jsQueue]() mutable {
    nativeToJsBridge_ = std::make_shared<NativeToJsBridge>(
        jsef.get(), moduleRegistry_, jsQueue, callback_);

    // 此处向js运行时注入全局对象nativeModuleProxy
    nativeToJsBridge_->initializeRuntime();

    /**
     * After NativeToJsBridge is created, the jsi::Runtime should exist.
     * Also, the JS message queue thread exists. So, it's safe to
     * schedule all queued up js Calls.
     */
    jsCallInvoker_->setNativeToJsBridgeAndFlushCalls(nativeToJsBridge_);

    std::scoped_lock lock(m_syncMutex);
    m_syncReady = true;
    m_syncCV.notify_all();
  });

  CHECK(nativeToJsBridge_);
}
public class NativeModuleRegistry {
  Collection<JavaModuleWrapper> getJavaModules(JSInstance jsInstance) {
    ArrayList<JavaModuleWrapper> javaModules = new ArrayList<>();
    for (Map.Entry<String, ModuleHolder> entry : mModules.entrySet()) {
      if (!entry.getValue().isCxxModule()) {
        javaModules.add(new JavaModuleWrapper(jsInstance, entry.getValue()));
      }
    }
    return javaModules;
  }
}

mNativeModuleRegistry.getJavaModules方法将所有模块封装成JavaModuleWrapper,以集合形式返回, JavaModuleWrapper中大量使用反射对模块实例进行操作,等下会讲到

// CatalystInstanceImpl.java
initializeBridge(
        new BridgeCallback(this),
        jsExecutor,
        mReactQueueConfiguration.getJSQueueThread(),
        mNativeModulesQueueThread,
        // 此处传入所有java模块
        mNativeModuleRegistry.getJavaModules(this),
        mNativeModuleRegistry.getCxxModules());

至此得到delegate对象,再看JSINativeModules实现

// ReactCommon\jsiexecutor\jsireact\JSINativeModules.h
class JSINativeModules {
 public:
  explicit JSINativeModules(std::shared_ptr<ModuleRegistry> moduleRegistry);
  jsi::Value getModule(jsi::Runtime& rt, const jsi::PropNameID& name);
  void reset();

 private:
  std::optional<jsi::Function> m_genNativeModuleJS;
  std::shared_ptr<ModuleRegistry> m_moduleRegistry;
  std::unordered_map<std::string, jsi::Object> m_objects;

  std::optional<jsi::Object> createModule(
      jsi::Runtime& rt,
      const std::string& name);
};
// ReactCommon\jsiexecutor\jsireact\JSINativeModules.cpp
JSINativeModules::JSINativeModules(
    std::shared_ptr<ModuleRegistry> moduleRegistry)
    : m_moduleRegistry(std::move(moduleRegistry)) {}

// NativeModuleProxy主要用到此方法
Value JSINativeModules::getModule(Runtime& rt, const PropNameID& name) {
  if (!m_moduleRegistry) {
    return nullptr;
  }

  std::string moduleName = name.utf8(rt);

  BridgeNativeModulePerfLogger::moduleJSRequireBeginningStart(
      moduleName.c_str());

  // m_objects是一个缓存模块实例的map,优先从map中获取实例
  const auto it = m_objects.find(moduleName);
  if (it != m_objects.end()) {
    BridgeNativeModulePerfLogger::moduleJSRequireBeginningCacheHit(
        moduleName.c_str());
    BridgeNativeModulePerfLogger::moduleJSRequireBeginningEnd(
        moduleName.c_str());
    return Value(rt, it->second);
  }

  // m_objects中不存在实例则创建一个
  auto module = createModule(rt, moduleName);
  if (!module.has_value()) {
    BridgeNativeModulePerfLogger::moduleJSRequireEndingFail(moduleName.c_str());
    // Allow lookup to continue in the objects own properties, which allows for
    // overrides of NativeModules
    return nullptr;
  }

  // 放入m_objects中缓存起来
  auto result =
      m_objects.emplace(std::move(moduleName), std::move(*module)).first;

  Value ret = Value(rt, result->second);
  BridgeNativeModulePerfLogger::moduleJSRequireEndingEnd(moduleName.c_str());
  return ret;
}

std::optional<Object> JSINativeModules::createModule(
    Runtime& rt,
    const std::string& name) {
  bool hasLogger(ReactMarker::logTaggedMarkerImpl);
  if (hasLogger) {
    ReactMarker::logTaggedMarker(
        ReactMarker::NATIVE_MODULE_SETUP_START, name.c_str());
  }

  if (!m_genNativeModuleJS) {
    m_genNativeModuleJS =
        rt.global().getPropertyAsFunction(rt, "__fbGenNativeModule");
  }

  // 通过JavaModuleWrapper暴露的反射方法实现动态分析模块的能力
  // 通过反射调用模块的getConstants方法,将常量放入结果中
  // 通过反射获取模块下的所有方法,并且获取注解的描述信息将方法区分为同步或者异步
  auto result = m_moduleRegistry->getConfig(name);
  if (!result.has_value()) {
    return std::nullopt;
  }

  Value moduleInfo = m_genNativeModuleJS->call(
      rt,
      valueFromDynamic(rt, result->config),
      static_cast<double>(result->index));
  CHECK(!moduleInfo.isNull()) << "Module returned from genNativeModule is null";
  CHECK(moduleInfo.isObject())
      << "Module returned from genNativeModule isn't an Object";

  std::optional<Object> module(
      moduleInfo.asObject(rt).getPropertyAsObject(rt, "module"));

  if (hasLogger) {
    ReactMarker::logTaggedMarker(
        ReactMarker::NATIVE_MODULE_SETUP_STOP, name.c_str());
  }

  return module;
}

至此获取java模块的配置信息

export type ModuleConfig = [
  string /* name */,
  ?{...} /* constants */,
  ?$ReadOnlyArray<string> /* functions */,
  ?$ReadOnlyArray<number> /* promise method IDs */,
  ?$ReadOnlyArray<number> /* sync method IDs */,
];

function genModule(
  config: ?ModuleConfig,
  moduleID: number,
): ?{
  name: string,
  module?: {...},
  ...
} {
  if (!config) {
    return null;
  }

  const [moduleName, constants, methods, promiseMethods, syncMethods] = config;
  invariant(
    !moduleName.startsWith('RCT') && !moduleName.startsWith('RK'),
    "Module name prefixes should've been stripped by the native side " +
      "but wasn't for " +
      moduleName,
  );

  if (!constants && !methods) {
    // Module contents will be filled in lazily later
    return {name: moduleName};
  }

  const module: {[string]: mixed} = {};
  methods &&
    methods.forEach((methodName, methodID) => {
      const isPromise =
        (promiseMethods && arrayContains(promiseMethods, methodID)) || false;
      const isSync =
        (syncMethods && arrayContains(syncMethods, methodID)) || false;
      invariant(
        !isPromise || !isSync,
        'Cannot have a method that is both async and a sync hook',
      );
      const methodType = isPromise ? 'promise' : isSync ? 'sync' : 'async';
      module[methodName] = genMethod(moduleID, methodID, methodType);
    });

  Object.assign(module, constants);

  if (module.getConstants == null) {
    module.getConstants = () => constants || Object.freeze({});
  } else {
    console.warn(
      `Unable to define method 'getConstants()' on NativeModule '${moduleName}'. NativeModule '${moduleName}' already has a constant or method called 'getConstants'. Please remove it.`,
    );
  }

  if (__DEV__) {
    BatchedBridge.createDebugLookup(moduleID, moduleName, methods);
  }

  return {name: moduleName, module};
}

// export this method as a global so we can call it from native
global.__fbGenNativeModule = genModule;

function genMethod(moduleID: number, methodID: number, type: MethodType) {
  let fn = null;
  if (type === 'promise') {
    fn = function promiseMethodWrapper(...args: Array<mixed>) {
      // In case we reject, capture a useful stack trace here.
      /* $FlowFixMe[class-object-subtyping] added when improving typing for
       * this parameters */
      const enqueueingFrameError: ExtendedError = new Error();
      return new Promise((resolve, reject) => {
        BatchedBridge.enqueueNativeCall(
          moduleID,
          methodID,
          args,
          data => resolve(data),
          errorData =>
            reject(
              updateErrorWithErrorData(
                (errorData: $FlowFixMe),
                enqueueingFrameError,
              ),
            ),
        );
      });
    };
  } else {
    fn = function nonPromiseMethodWrapper(...args: Array<mixed>) {
      const lastArg = args.length > 0 ? args[args.length - 1] : null;
      const secondLastArg = args.length > 1 ? args[args.length - 2] : null;
      const hasSuccessCallback = typeof lastArg === 'function';
      const hasErrorCallback = typeof secondLastArg === 'function';
      hasErrorCallback &&
        invariant(
          hasSuccessCallback,
          'Cannot have a non-function arg after a function arg.',
        );
      // $FlowFixMe[incompatible-type]
      const onSuccess: ?(mixed) => void = hasSuccessCallback ? lastArg : null;
      // $FlowFixMe[incompatible-type]
      const onFail: ?(mixed) => void = hasErrorCallback ? secondLastArg : null;
      // $FlowFixMe[unsafe-addition]
      const callbackCount = hasSuccessCallback + hasErrorCallback;
      const newArgs = args.slice(0, args.length - callbackCount);
      if (type === 'sync') {
        return BatchedBridge.callNativeSyncHook(
          moduleID,
          methodID,
          newArgs,
          onFail,
          onSuccess,
        );
      } else {
        BatchedBridge.enqueueNativeCall(
          moduleID,
          methodID,
          newArgs,
          onFail,
          onSuccess,
        );
      }
    };
  }
  // $FlowFixMe[prop-missing]
  fn.type = type;
  return fn;
}

调用js全局方法__fbGenNativeModule生成对应java模块的js对象,此时访问该对象会包含java模块下的配置信息,包括模块名常量与所有方法,通过genMethod可以发现调用模块方法时同步方法使用BatchedBridge.callNativeSyncHook,异步方法使用BatchedBridge.enqueueNativeCall,至此js侧得到了访问对应java模块的能力,接下来看如何调用java模块方法并获得方法返回内容。

// Libraries\BatchedBridge\BatchedBridge.js
'use strict';

const MessageQueue = require('./MessageQueue');

const BatchedBridge: MessageQueue = new MessageQueue();

// Wire up the batched bridge on the global object so that we can call into it.
// Ideally, this would be the inverse relationship. I.e. the native environment
// provides this global directly with its script embedded. Then this module
// would export it. A possible fix would be to trim the dependencies in
// MessageQueue to its minimal features and embed that in the native runtime.

Object.defineProperty(global, '__fbBatchedBridge', {
  configurable: true,
  value: BatchedBridge,
});

module.exports = BatchedBridge;

// Libraries\BatchedBridge\MessageQueue.js
class MessageQueue {
  callNativeSyncHook(
    moduleID: number,
    methodID: number,
    params: mixed[],
    onFail: ?(...mixed[]) => void,
    onSucc: ?(...mixed[]) => void,
  ): mixed {
    // 注册回调方法
    this.processCallbacks(moduleID, methodID, params, onFail, onSucc);
    // 调用通过jsi注册的cpp方法
    return global.nativeCallSyncHook(moduleID, methodID, params);
  }
  
   enqueueNativeCall(
    moduleID: number,
    methodID: number,
    params: mixed[],
    onFail: ?(...mixed[]) => void,
    onSucc: ?(...mixed[]) => void,
  ): void {
    this.processCallbacks(moduleID, methodID, params, onFail, onSucc);

    this._queue[MODULE_IDS].push(moduleID);
    this._queue[METHOD_IDS].push(methodID);

      // Replacement allows normally non-JSON-convertible values to be
      // seen.  There is ambiguity with string values, but in context,
      // it should at least be a strong hint.
      const replacer = (key: string, val: $FlowFixMe) => {
        const t = typeof val;
        if (t === 'function') {
          return '<<Function ' + val.name + '>>';
        } else if (t === 'number' && !isFinite(val)) {
          return '<<' + val.toString() + '>>';
        } else {
          return val;
        }
      };

      // Note that JSON.stringify
      invariant(
        isValidArgument(params),
        '%s is not usable as a native method argument',
        JSON.stringify(params, replacer),
      );

      // The params object should not be mutated after being queued
      deepFreezeAndThrowOnMutationInDev(params);
    }
    this._queue[PARAMS].push(params);

    const now = Date.now();
    if (
      global.nativeFlushQueueImmediate &&
      now - this._lastFlush >= MIN_TIME_BETWEEN_FLUSHES_MS
    ) {
      const queue = this._queue;
      this._queue = [[], [], [], this._callID];
      this._lastFlush = now;
      global.nativeFlushQueueImmediate(queue);
    }
    Systrace.counterEvent('pending_js_to_native_queue', this._queue[0].length);
    if (__DEV__ && this.__spy && isFinite(moduleID)) {
      // $FlowFixMe[not-a-function]
      this.__spy({
        type: TO_NATIVE,
        module: this._remoteModuleTable[moduleID],
        method: this._remoteMethodTable[moduleID][methodID],
        args: params,
      });
    } else if (this.__spy) {
      this.__spy({
        type: TO_NATIVE,
        module: moduleID + '',
        method: methodID,
        args: params,
      });
    }
  }

 processCallbacks(
    moduleID: number,
    methodID: number,
    params: mixed[],
    onFail: ?(...mixed[]) => void,
    onSucc: ?(...mixed[]) => void,
  ): void {
    if (onFail || onSucc) {
      // Encode callIDs into pairs of callback identifiers by shifting left and using the rightmost bit
      // to indicate fail (0) or success (1)
      // eslint-disable-next-line no-bitwise
      onFail && params.push(this._callID << 1);
      // eslint-disable-next-line no-bitwise
      onSucc && params.push((this._callID << 1) | 1);
      this._successCallbacks.set(this._callID, onSucc);
      this._failureCallbacks.set(this._callID, onFail);
    }
    this._callID++;
  }
}

梳理流程

  1. CatalsyInstanceImpl中调用initializeBridge方式通过jni的方式初始化NativeToJsBridge.
  2. NativeToJsBridge构造方法中初始化JsToNativeBridge与JSExecutor,其中JsToNativeBridge构建时包含initializeBridge方法传入的ModuleRegistry,ModuleRegistry是一个向量包含所有的javaModules与cxxModules,JSIExecutor在构造时会得到JsToNativeBridge即delegate.
  3. JSIExecutor初始化过程中生成一个JSINativeModules对象,该对象构造方法通过delegate->getModuleRegistry()获取到ModuleRegistry,如此JSINativeModules就获得了访问所有javaModules的能力.
  4. initializeBridge方法调用到JSIExecutor的initializeRuntime方法,该方法会通过jsi向js运行时全局注入一个名为nativeModuleProxy的对象,该对象初始化时接收JSINativeModules,因此js运行时也具有了访问所有javaModules的能力.
  5. 当js侧访问模块时,会调用JSINativeModules的getModule方法,getModule在第一次获取某个模块会调用createModule方法在ModuleRegistry获取到对应模块在向量中的下标此为moduleID,利用JavaModuleWrapper提供的反射方法分析模块的配置,包括模块名和模块的常量和模块下的所有方法(包含注解信息以区分同步方法和异步方法类型)此为config,随后调用js全局方法__fbGenNativeModule传入config和moduleId生成js对象,至此js侧获得对应java模块的js对象.

章节总结
CatalsyInstanceImpl中通过jni调用cpp初始化JSIExecutor,当js侧访问对应java模块时,cpp通过jni调用java的反射方法分析java模块获得模块信息config,之后cpp通过jsi调用js侧全局方法__fbGenNativeModule传入模块信息config生成对应java模块的js对象返回给js侧,至此js侧可以获取对应java模块的js对象,该对象下有java模块下的模块名、常量、所有方法,达到分析java模块的目的。

1.2 同步方法调用

先看同步调用global.nativeCallSyncHook的实现

// ReactCommon\jsiexecutor\jsireact\JSIExecutor.cpp
void JSIExecutor::initializeRuntime() {
  runtime_->global().setProperty(
      *runtime_,
      "nativeCallSyncHook",
      Function::createFromHostFunction(
          *runtime_,
          PropNameID::forAscii(*runtime_, "nativeCallSyncHook"),
          1,
          [this](
              jsi::Runtime&,
              const jsi::Value&,
              const jsi::Value* args,
              size_t count) { return nativeCallSyncHook(args, count); }));
}

Value JSIExecutor::nativeCallSyncHook(const Value* args, size_t count) {
  if (count != 3) {
    throw std::invalid_argument("nativeCallSyncHook arg count must be 3");
  }

  if (!args[2].isObject() || !args[2].asObject(*runtime_).isArray(*runtime_)) {
    throw std::invalid_argument(
        folly::to<std::string>("method parameters should be array"));
  }

  unsigned int moduleId = static_cast<unsigned int>(args[0].getNumber());
  unsigned int methodId = static_cast<unsigned int>(args[1].getNumber());
  std::string moduleName;
  std::string methodName;

  if (moduleRegistry_) {
    moduleName = moduleRegistry_->getModuleName(moduleId);
    methodName = moduleRegistry_->getModuleSyncMethodName(moduleId, methodId);

    BridgeNativeModulePerfLogger::syncMethodCallStart(
        moduleName.c_str(), methodName.c_str());

    BridgeNativeModulePerfLogger::syncMethodCallArgConversionStart(
        moduleName.c_str(), methodName.c_str());
  }

  // 关键调用
  MethodCallResult result = delegate_->callSerializableNativeHook(
      *this, moduleId, methodId, dynamicFromValue(*runtime_, args[2]));

  /**
   * Note:
   * In RCTNativeModule, std::nullopt is returned from
   * callSerializableNativeHook when executing a NativeModule method fails.
   * Therefore, it's safe to not terminate the syncMethodCall when std::nullopt
   * is returned.
   *
   * TODO: In JavaNativeModule, std::nullopt is returned when the synchronous
   * NativeModule method has the void return type. Change this to return
   * folly::dynamic(nullptr) instead, so that std::nullopt is reserved for
   * exceptional scenarios.
   *
   * TODO: Investigate CxxModule infra to see if std::nullopt is used for
   * returns in exceptional scenarios.
   **/

  if (!result.has_value()) {
    return Value::undefined();
  }

  Value returnValue = valueFromDynamic(*runtime_, result.value());

  if (moduleRegistry_) {
    BridgeNativeModulePerfLogger::syncMethodCallReturnConversionEnd(
        moduleName.c_str(), methodName.c_str());
    BridgeNativeModulePerfLogger::syncMethodCallEnd(
        moduleName.c_str(), methodName.c_str());
  }

  return returnValue;
}

通过jsi全局注入nativeCallSyncHook方法, 调用类型为JsToNativeBridgedelegate_对象的callSerializableNativeHook方法

// ReactCommon\cxxreact\NativeToJsBridge.cpp
class JsToNativeBridge : public react::ExecutorDelegate {
  MethodCallResult callSerializableNativeHook(
      [[maybe_unused]] JSExecutor& executor,
      unsigned int moduleId,
      unsigned int methodId,
      folly::dynamic&& args) override {
    return m_registry->callSerializableNativeHook(
        moduleId, methodId, std::move(args));
  }
}
// ReactCommon\cxxreact\ModuleRegistry.cpp
MethodCallResult ModuleRegistry::callSerializableNativeHook(
    unsigned int moduleId,
    unsigned int methodId,
    folly::dynamic&& params) {
  if (moduleId >= modules_.size()) {
    throw std::runtime_error(folly::to<std::string>(
        "moduleId ", moduleId, "out of range [0..", modules_.size(), ")"));
  }
  return modules_[moduleId]->callSerializableNativeHook(
      methodId, std::move(params));
}
// ReactAndroid\src\main\jni\react\jni\JavaModuleWrapper.cpp
MethodCallResult JavaNativeModule::callSerializableNativeHook(
    unsigned int reactMethodId,
    folly::dynamic&& params) {
  // TODO: evaluate whether calling through invoke is potentially faster
  if (reactMethodId >= syncMethods_.size()) {
    throw std::invalid_argument(folly::to<std::string>(
        "methodId ",
        reactMethodId,
        " out of range [0..",
        syncMethods_.size(),
        "]"));
  }

  auto& method = syncMethods_[reactMethodId];
  CHECK(method.has_value() && method->isSyncHook())
      << "Trying to invoke a asynchronous method as synchronous hook";
  return method->invoke(instance_, wrapper_->getModule(), params);
}

//  ReactAndroid\src\main\java\com\facebook\react\bridge\JavaModuleWrapper.java
class JavaModuleWrapper {
  @DoNotStrip
  public void invoke(int methodId, ReadableNativeArray parameters) {
    if (mMethods == null || methodId >= mMethods.size()) {
      return;
    }

    mMethods.get(methodId).invoke(mJSInstance, parameters);
  }
}

class JavaMethodWrapper implements NativeModule.NativeMethod {
@Override
  public void invoke(JSInstance jsInstance, ReadableArray parameters) {
    try {
      if (!mArgumentsProcessed) {
        processArguments();
      }
      if (mArguments == null || mArgumentExtractors == null) {
        throw new Error("processArguments failed");
      }
      if (mJSArgumentsNeeded != parameters.size()) {
        throw new NativeArgumentsParseException(
            traceName + " got " + parameters.size() + " arguments, expected " + mJSArgumentsNeeded);
      }

      int i = 0, jsArgumentsConsumed = 0;
      try {
        for (; i < mArgumentExtractors.length; i++) {
          mArguments[i] =
              mArgumentExtractors[i].extractArgument(jsInstance, parameters, jsArgumentsConsumed);
          jsArgumentsConsumed += mArgumentExtractors[i].getJSArgumentsNeeded();
        }
      } catch (UnexpectedNativeTypeException | NullPointerException e) {
        throw new NativeArgumentsParseException(
            e.getMessage()
                + " (constructing arguments for "
                + traceName
                + " at argument index "
                + getAffectedRange(
                    jsArgumentsConsumed, mArgumentExtractors[i].getJSArgumentsNeeded())
                + ")",
            e);
      }

      try {
        // 最终通过反射执行模块对应方法
        mMethod.invoke(mModuleWrapper.getModule(), mArguments);
      } catch (IllegalArgumentException | IllegalAccessException e) {
        throw new RuntimeException(createInvokeExceptionMessage(traceName), e);
      } catch (InvocationTargetException ite) {
        // Exceptions thrown from native module calls end up wrapped in InvocationTargetException
        // which just make traces harder to read and bump out useful information
        if (ite.getCause() instanceof RuntimeException) {
          throw (RuntimeException) ite.getCause();
        }
        throw new RuntimeException(createInvokeExceptionMessage(traceName), ite);
      }
    } finally {
      SystraceMessage.endSection(TRACE_TAG_REACT_JAVA_BRIDGE).flush();
    }
  }
}

章节总结
cpp通过jsi注入的名为nativeCallSyncHook的js全局方法,在分析模块时产生的js对象通过闭包的方法保存了moduleId、metheId,调用js对象下的指定java模块方法时会将两个id与函数入参传达给cpp,cpp通过根据两个id找到对应模块和对应方法通过反射执行方法拿到执行结果,最终cpp通过jni返回执行结果给js侧。

1.3 异步方法调用

待续

2. Java调用js方法

待续