-
Notifications
You must be signed in to change notification settings - Fork 12
Description
Summary
When running the application on Android using React Native 0.81.2, the app crashes immediately upon startup with a JNI error. The error indicates a missing mHybridData field in CallInvokerHolderImpl.
This appears to be caused by internal changes in React Native 0.80+, where the JNI HybridData structure for CallInvoker was modified, breaking the existing implementation in cpp-adapter.cpp.
Environment
- React Native Version: 0.81.2
- Platform: Android
- Library Version: Current
Stack Trace
java_vm_ext.cc:591] JNI DETECTED ERROR IN APPLICATION: JNI GetObjectField called with pending exception java.lang.NoSuchFieldError: no "Lcom/facebook/jni/HybridData;" field "mHybridData" in class "Lcom/facebook/react/turbomodule/core/CallInvokerHolderImpl;" or its superclasses
java_vm_ext.cc:591] at boolean com.unomed.reactnativematrixsdk.ReactNativeMatrixSdkModule.nativeInstallRustCrate(long, com.facebook.react.turbomodule.core.interfaces.CallInvokerHolder) (ReactNativeMatrixSdkModule.kt:-2)
java_vm_ext.cc:591] at boolean com.unomed.reactnativematrixsdk.ReactNativeMatrixSdkModule.installRustCrate() (ReactNativeMatrixSdkModule.kt:24)
java_vm_ext.cc:591] at void com.facebook.jni.NativeRunnable.run() (NativeRunnable.java:-2)
java_vm_ext.cc:591] at void android.os.Handler.handleCallback(android.os.Message) (Handler.java:958)
java_vm_ext.cc:591] at void android.os.Handler.dispatchMessage(android.os.Message) (Handler.java:99)
java_vm_ext.cc:591] at void com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(android.os.Message) (MessageQueueThreadHandler.kt:21)
java_vm_ext.cc:591] at boolean android.os.Looper.loopOnce(android.os.Looper, long, int) (Looper.java:205)
java_vm_ext.cc:591] at void android.os.Looper.loop() (Looper.java:294)
java_vm_ext.cc:591] at void com.facebook.react.bridge.queue.MessageQueueThreadImpl$Companion.startNewBackgroundThread$lambda$0(com.facebook.react.common.futures.SimpleSettableFuture) (MessageQueueThreadImpl.kt:152)
java_vm_ext.cc:591] at void com.facebook.react.bridge.queue.MessageQueueThreadImpl$Companion.$r8$lambda$YYXYCFexeoKtAeDpeNYkxZZlpbA(com.facebook.react.common.futures.SimpleSettableFuture) (MessageQueueThreadImpl.kt:-1)
java_vm_ext.cc:591] at void com.facebook.react.bridge.queue.MessageQueueThreadImpl$Companion$$ExternalSyntheticLambda0.run() (D8$$SyntheticClass:0)
java_vm_ext.cc:591] at void java.lang.Thread.run() (Thread.java:1012)
java_vm_ext.cc:591]
java_vm_ext.cc:591] in call to GetObjectField
java_vm_ext.cc:591] from boolean com.unomed.reactnativematrixsdk.ReactNativeMatrixSdkModule.nativeInstallRustCrate(long, com.facebook.react.turbomodule.core.interfaces.CallInvokerHolder)
Proposed Solution
I found a solution based on a similar issue in the uniffi-bindgen-react-native repo (Issue #295). We need to update how we cast the CallInvokerHolder in C++ to use fbjni references properly instead of looking for the raw field.
I have successfully patched this locally. Here are the required changes to android/cpp-adapter.cpp in the format of a patch file:
File: patches/@unomed+react-native-matrix-sdk+0.8.1.patch
diff --git a/node_modules/@unomed/react-native-matrix-sdk/android/cpp-adapter.cpp b/node_modules/@unomed/react-native-matrix-sdk/android/cpp-adapter.cpp
index 1656417..893cb0b 100644
--- a/node_modules/@unomed/react-native-matrix-sdk/android/cpp-adapter.cpp
+++ b/node_modules/@unomed/react-native-matrix-sdk/android/cpp-adapter.cpp
@@ -2,6 +2,7 @@
#include <jni.h>
#include <jsi/jsi.h>
#include <ReactCommon/CallInvokerHolder.h>
+#include <fbjni/fbjni.h>
#include "unomed-react-native-matrix-sdk.h"
namespace jsi = facebook::jsi;
@@ -24,6 +25,8 @@ Java_com_unomed_reactnativematrixsdk_ReactNativeMatrixSdkModule_nativeInstallRus
jlong rtPtr,
jobject callInvokerHolderJavaObj
) {
+ /** The following code used to work, but since React Native 0.80+, it stopped working on Android so this is the fix.
+
// https://github.com/realm/realm-js/blob/main/packages/realm/binding/android/src/main/cpp/io_realm_react_RealmReactModule.cpp#L122-L145
// React Native uses the fbjni library for handling JNI, which has the concept of "hybrid objects",
// which are Java objects containing a pointer to a C++ object. The CallInvokerHolder, which has the
@@ -53,6 +56,30 @@ Java_com_unomed_reactnativematrixsdk_ReactNativeMatrixSdkModule_nativeInstallRus
auto runtime = reinterpret_cast<jsi::Runtime *>(rtPtr);
return unomed_reactnativematrixsdk::installRustCrate(*runtime, jsCallInvoker);
+
+ **/
+
+ try {
+ if (callInvokerHolderJavaObj == nullptr) {
+ return false;
+ }
+
+ auto alias = facebook::jni::alias_ref<jobject>(callInvokerHolderJavaObj);
+ auto holder = facebook::jni::static_ref_cast<facebook::react::CallInvokerHolder::javaobject>(alias);
+ if (!holder) {
+ return false;
+ }
+
+ auto jsCallInvoker = holder->cthis()->getCallInvoker();
+ if (!jsCallInvoker) {
+ return false;
+ }
+
+ auto runtime = reinterpret_cast<jsi::Runtime *>(rtPtr);
+ return unomed_reactnativematrixsdk::installRustCrate(*runtime, jsCallInvoker);
+ } catch (...) {
+ return false;
+ }
}
extern "C"
References
- Fix inspiration:
mHybridDatafield access causes crash on React Native 0.80+ and expo 54 - Android compatibility issue jhugman/uniffi-bindgen-react-native#295
Steps to Reproduce
- Initialize a React Native project with version
0.81.2. - Install
@unomed-dev/react-native-matrix-sdk. - Attempt to run on Android.
- App crashes on launch with JNI error.