diff --git a/CHANGELOG.md b/CHANGELOG.md index 45f1c98a43..d3f65a203e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ ### Fixed * Using keypaths in Flows could sometimes throw `java.lang.IllegalStateException: [RLM_ERR_WRONG_THREAD]: Realm accessed from incorrect thread.`. (Issue [#1594](https://github.com/realm/realm-kotlin/pull/1594, since 1.13.0) +* Cache notification callback JNI references at startup to ensure that symbols can be resolved in core callbacks. (Issue [#1577](https://github.com/realm/realm-kotlin/issues/1577)) ### Compatibility * File format: Generates Realms with file format v23. diff --git a/packages/cinterop/src/jvm/jni/java_class_global_def.hpp b/packages/cinterop/src/jvm/jni/java_class_global_def.hpp index 92b9d2562e..c35f41f903 100644 --- a/packages/cinterop/src/jvm/jni/java_class_global_def.hpp +++ b/packages/cinterop/src/jvm/jni/java_class_global_def.hpp @@ -66,6 +66,7 @@ class JavaClassGlobalDef { , m_io_realm_kotlin_internal_interop_app_callback(env, "io/realm/kotlin/internal/interop/AppCallback", false) , m_io_realm_kotlin_internal_interop_connection_state_change_callback(env, "io/realm/kotlin/internal/interop/ConnectionStateChangeCallback", false) , m_io_realm_kotlin_internal_interop_sync_thread_observer(env, "io/realm/kotlin/internal/interop/SyncThreadObserver", false) + , m_io_realm_kotlin_internal_interop_notification_callback(env, "io/realm/kotlin/internal/interop/NotificationCallback", false) { } @@ -92,6 +93,7 @@ class JavaClassGlobalDef { jni_util::JavaClass m_io_realm_kotlin_internal_interop_app_callback; jni_util::JavaClass m_io_realm_kotlin_internal_interop_connection_state_change_callback; jni_util::JavaClass m_io_realm_kotlin_internal_interop_sync_thread_observer; + jni_util::JavaClass m_io_realm_kotlin_internal_interop_notification_callback; inline static std::unique_ptr& instance() { @@ -219,6 +221,11 @@ class JavaClassGlobalDef { return instance()->m_io_realm_kotlin_internal_interop_sync_thread_observer; } + inline static const jni_util::JavaClass& notification_callback() + { + return instance()->m_io_realm_kotlin_internal_interop_notification_callback; + } + inline static const jni_util::JavaMethod function0Method(JNIEnv* env) { return jni_util::JavaMethod(env, instance()->m_kotlin_jvm_functions_function0, "invoke", "()Ljava/lang/Object;"); diff --git a/packages/jni-swig-stub/src/main/jni/realm_api_helpers.cpp b/packages/jni-swig-stub/src/main/jni/realm_api_helpers.cpp index cef1c08e7b..dbb7531306 100644 --- a/packages/jni-swig-stub/src/main/jni/realm_api_helpers.cpp +++ b/packages/jni-swig-stub/src/main/jni/realm_api_helpers.cpp @@ -173,8 +173,8 @@ register_results_notification_cb(realm_results_t *results, int64_t key_path_array_ptr, jobject callback) { auto jenv = get_env(); - static jclass notification_class = jenv->FindClass("io/realm/kotlin/internal/interop/NotificationCallback"); - static jmethodID on_change_method = jenv->GetMethodID(notification_class, "onChange", "(J)V"); + static JavaMethod on_change_method(jenv, JavaClassGlobalDef::notification_callback(), + "onChange", "(J)V"); return realm_results_add_notification_callback( results, @@ -201,8 +201,8 @@ register_results_notification_cb(realm_results_t *results, realm_on_object_change_func_t get_on_object_change() { auto jenv = get_env(true); - static jclass notification_class = jenv->FindClass("io/realm/kotlin/internal/interop/NotificationCallback"); - static jmethodID on_change_method = jenv->GetMethodID(notification_class, "onChange", "(J)V"); + static JavaMethod on_change_method(jenv, JavaClassGlobalDef::notification_callback(), + "onChange", "(J)V"); return [](realm_userdata_t userdata, const realm_object_changes_t* changes) { // TODO API-NOTIFICATION Consider catching errors and propagate to error callback // like the C-API error callback below @@ -218,8 +218,8 @@ realm_on_object_change_func_t get_on_object_change() { realm_on_collection_change_func_t get_on_collection_change() { auto jenv = get_env(true); - static jclass notification_class = jenv->FindClass("io/realm/kotlin/internal/interop/NotificationCallback"); - static jmethodID on_change_method = jenv->GetMethodID(notification_class, "onChange", "(J)V"); + static JavaMethod on_change_method(jenv, JavaClassGlobalDef::notification_callback(), + "onChange", "(J)V"); return [](realm_userdata_t userdata, const realm_collection_changes_t* changes) { // TODO API-NOTIFICATION Consider catching errors and propagate to error callback // like the C-API error callback below @@ -235,8 +235,8 @@ realm_on_collection_change_func_t get_on_collection_change() { realm_on_dictionary_change_func_t get_on_dictionary_change() { auto jenv = get_env(true); - static jclass notification_class = jenv->FindClass("io/realm/kotlin/internal/interop/NotificationCallback"); - static jmethodID on_change_method = jenv->GetMethodID(notification_class, "onChange", "(J)V"); + static JavaMethod on_change_method(jenv, JavaClassGlobalDef::notification_callback(), + "onChange", "(J)V"); return [](realm_userdata_t userdata, const realm_dictionary_changes_t* changes) { // TODO API-NOTIFICATION Consider catching errors and propagate to error callback // like the C-API error callback below