realm / realm-kotlin

Kotlin Multiplatform and Android SDK for the Realm Mobile Database: Build Better Apps Faster.
Apache License 2.0
962 stars 61 forks source link

Assertion failed: m_method_id != nullptr #1401

Closed DamianJaeger closed 1 year ago

DamianJaeger commented 1 year ago

SDK and version

SDK : Kotlin Version: 1.8.0

Observations

Crash log / stacktrace

11:37:49.472 27037-27179 REALM                          <app-package-name>       E  /Users/realm/workspace-realm-kotlin/releases/packages/cinterop/src/jvm/jni/java_method.cpp:33: [realm-core-13.10.0] Assertion failed: m_method_id != nullptr with (method_name, signature) =  ["asThrowable", "(Lio/realm/kotlin/internal/interop/RealmCoreException;)Ljava/lang/Throwable;"]
                                                                                 <backtrace not supported on this platform>
                                                                                 !!! IMPORTANT: Please report this at https://github.com/realm/realm-core/issues/new/choose
11:37:49.473 27037-27179 libc                           <app-package-name>       A  Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 27179 (SyncThread-<app-name>), pid 27037 (<app-package-name>)
11:37:49.651 27188-27188 DEBUG                          pid-27188             A  Cmdline: <app-package-name>
11:37:49.651 27188-27188 DEBUG                          pid-27188             A  pid: 27037, tid: 27179, name: SyncThread-<app-name>  >>> <app-package-name> <<<
11:37:49.654 27188-27188 DEBUG                          pid-27188             A        realm/realm-core#1 pc 0000000000728305  /data/app/~~1bsexmCci6vx6HbC46nkhA==/<app-package-name>-QuDZ7iD8i2uRoGbwSLuzeQ==/lib/x86_64/librealmc.so (BuildId: d04f2a18ff690e7bec1a86a262aa1081a82ff7c2)
11:37:49.654 27188-27188 DEBUG                          pid-27188             A        realm/realm-core#2 pc 0000000000728660  /data/app/~~1bsexmCci6vx6HbC46nkhA==/<app-package-name>-QuDZ7iD8i2uRoGbwSLuzeQ==/lib/x86_64/librealmc.so (BuildId: d04f2a18ff690e7bec1a86a262aa1081a82ff7c2)
11:37:49.654 27188-27188 DEBUG                          pid-27188             A        realm/realm-core#3 pc 00000000007284f0  /data/app/~~1bsexmCci6vx6HbC46nkhA==/<app-package-name>-QuDZ7iD8i2uRoGbwSLuzeQ==/lib/x86_64/librealmc.so (BuildId: d04f2a18ff690e7bec1a86a262aa1081a82ff7c2)
11:37:49.654 27188-27188 DEBUG                          pid-27188             A        realm/realm-core#4 pc 00000000003660c3  /data/app/~~1bsexmCci6vx6HbC46nkhA==/<app-package-name>-QuDZ7iD8i2uRoGbwSLuzeQ==/lib/x86_64/librealmc.so (void realm::util::terminate_with_info<char const*&, char const*&>(char const*, int, char const*, char const*, char const*&, char const*&)+115) (BuildId: d04f2a18ff690e7bec1a86a262aa1081a82ff7c2)
11:37:49.655 27188-27188 DEBUG                          pid-27188             A        realm/realm-core#5 pc 000000000036603d  /data/app/~~1bsexmCci6vx6HbC46nkhA==/<app-package-name>-QuDZ7iD8i2uRoGbwSLuzeQ==/lib/x86_64/librealmc.so (realm::jni_util::JavaMethod::JavaMethod(_JNIEnv*, realm::jni_util::JavaClass const&, char const*, char const*, bool)+141) (BuildId: d04f2a18ff690e7bec1a86a262aa1081a82ff7c2)
11:37:49.655 27188-27188 DEBUG                          pid-27188             A        realm/realm-core#6 pc 0000000000361cd5  /data/app/~~1bsexmCci6vx6HbC46nkhA==/<app-package-name>-QuDZ7iD8i2uRoGbwSLuzeQ==/lib/x86_64/librealmc.so (realm_async_open_task_callback(void*, realm_thread_safe_reference*, realm_async_error const*)+901) (BuildId: d04f2a18ff690e7bec1a86a262aa1081a82ff7c2)
11:37:49.656 27188-27188 DEBUG                          pid-27188             A        realm/realm-core#7 pc 000000000039b805  /data/app/~~1bsexmCci6vx6HbC46nkhA==/<app-package-name>-QuDZ7iD8i2uRoGbwSLuzeQ==/lib/x86_64/librealmc.so (BuildId: d04f2a18ff690e7bec1a86a262aa1081a82ff7c2)
11:37:49.656 27188-27188 DEBUG                          pid-27188             A        realm/realm-core#8 pc 00000000004504e4  /data/app/~~1bsexmCci6vx6HbC46nkhA==/<app-package-name>-QuDZ7iD8i2uRoGbwSLuzeQ==/lib/x86_64/librealmc.so (BuildId: d04f2a18ff690e7bec1a86a262aa1081a82ff7c2)
11:37:49.656 27188-27188 DEBUG                          pid-27188             A        realm/realm-core#9 pc 00000000004691b6  /data/app/~~1bsexmCci6vx6HbC46nkhA==/<app-package-name>-QuDZ7iD8i2uRoGbwSLuzeQ==/lib/x86_64/librealmc.so (BuildId: d04f2a18ff690e7bec1a86a262aa1081a82ff7c2)
11:37:49.656 27188-27188 DEBUG                          pid-27188             A        realm/realm-core#10 pc 000000000053cd4a  /data/app/~~1bsexmCci6vx6HbC46nkhA==/<app-package-name>-QuDZ7iD8i2uRoGbwSLuzeQ==/lib/x86_64/librealmc.so (BuildId: d04f2a18ff690e7bec1a86a262aa1081a82ff7c2)
11:37:49.656 27188-27188 DEBUG                          pid-27188             A        realm/realm-core#11 pc 00000000005505c2  /data/app/~~1bsexmCci6vx6HbC46nkhA==/<app-package-name>-QuDZ7iD8i2uRoGbwSLuzeQ==/lib/x86_64/librealmc.so (BuildId: d04f2a18ff690e7bec1a86a262aa1081a82ff7c2)
11:37:49.656 27188-27188 DEBUG                          pid-27188             A        realm/realm-core#12 pc 00000000005504f8  /data/app/~~1bsexmCci6vx6HbC46nkhA==/<app-package-name>-QuDZ7iD8i2uRoGbwSLuzeQ==/lib/x86_64/librealmc.so (BuildId: d04f2a18ff690e7bec1a86a262aa1081a82ff7c2)
11:37:49.657 27188-27188 DEBUG                          pid-27188             A        realm/realm-core#13 pc 000000000054bc0d  /data/app/~~1bsexmCci6vx6HbC46nkhA==/<app-package-name>-QuDZ7iD8i2uRoGbwSLuzeQ==/lib/x86_64/librealmc.so (BuildId: d04f2a18ff690e7bec1a86a262aa1081a82ff7c2)
11:37:49.657 27188-27188 DEBUG                          pid-27188             A        realm/realm-core#14 pc 0000000000555931  /data/app/~~1bsexmCci6vx6HbC46nkhA==/<app-package-name>-QuDZ7iD8i2uRoGbwSLuzeQ==/lib/x86_64/librealmc.so (BuildId: d04f2a18ff690e7bec1a86a262aa1081a82ff7c2)
11:37:49.657 27188-27188 DEBUG                          pid-27188             A        realm/realm-core#15 pc 00000000005b29e3  /data/app/~~1bsexmCci6vx6HbC46nkhA==/<app-package-name>-QuDZ7iD8i2uRoGbwSLuzeQ==/lib/x86_64/librealmc.so (BuildId: d04f2a18ff690e7bec1a86a262aa1081a82ff7c2)
11:37:49.657 27188-27188 DEBUG                          pid-27188             A        realm/realm-core#16 pc 00000000005a65cd  /data/app/~~1bsexmCci6vx6HbC46nkhA==/<app-package-name>-QuDZ7iD8i2uRoGbwSLuzeQ==/lib/x86_64/librealmc.so (BuildId: d04f2a18ff690e7bec1a86a262aa1081a82ff7c2)
11:37:49.657 27188-27188 DEBUG                          pid-27188             A        realm/realm-core#17 pc 00000000005abd64  /data/app/~~1bsexmCci6vx6HbC46nkhA==/<app-package-name>-QuDZ7iD8i2uRoGbwSLuzeQ==/lib/x86_64/librealmc.so (BuildId: d04f2a18ff690e7bec1a86a262aa1081a82ff7c2)
11:37:49.657 27188-27188 DEBUG                          pid-27188             A        realm/realm-core#18 pc 000000000059e337  /data/app/~~1bsexmCci6vx6HbC46nkhA==/<app-package-name>-QuDZ7iD8i2uRoGbwSLuzeQ==/lib/x86_64/librealmc.so (BuildId: d04f2a18ff690e7bec1a86a262aa1081a82ff7c2)
11:37:49.657 27188-27188 DEBUG                          pid-27188             A        realm/realm-core#19 pc 000000000059fdc7  /data/app/~~1bsexmCci6vx6HbC46nkhA==/<app-package-name>-QuDZ7iD8i2uRoGbwSLuzeQ==/lib/x86_64/librealmc.so (BuildId: d04f2a18ff690e7bec1a86a262aa1081a82ff7c2)

Steps & Code to Reproduce

nicola-cab commented 1 year ago

Hello, thanks for reporting this, it seems there is some assertion that got triggered in the JNI code which is supposed to call into realm core. @cmelchior can you shed some light here?

cmelchior commented 1 year ago

It looks like a problem with ProGuard or DexGuard. JNI cannot call back into the JVM if the methods there are obfuscated.

We do ship proguard files that should automatically handle this for Android, but this doesn't work automatically for JVM and we have seen issues with DexGuard sometimes not applying it correctly.

@DamianJaeger I'll move this issue to realm-kotlin and we will continue the discussion there. But does any of the above apply to your project?

DamianJaeger commented 1 year ago

Methods should not be obfuscated, it is a debug build with neither ProGuard nor DexGuard enabled.

cmelchior commented 1 year ago

Is it a JVM or Android project?

DamianJaeger commented 1 year ago

Android

cmelchior commented 1 year ago

Hmm, that sounds weird. Can you post your build.gradle file? Or can you share the project showing this behavior?

DamianJaeger commented 1 year ago

It is a multi-module project and I can not share it in its entirety. Here are the project and app level build files:

Project level build.gradle.kts:

buildscript {

    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath("com.android.tools.build:gradle:8.0.1")
        classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.21")
        classpath("com.google.dagger:hilt-android-gradle-plugin:2.45")
        classpath("com.google.gms:google-services:4.3.15")
        classpath("io.realm.kotlin:gradle-plugin:1.8.0")
    }
}

plugins {
    id("io.realm.kotlin") version "1.8.0" apply false
}

allprojects {
    repositories {
        google()
        mavenCentral()
    }
}

tasks.register("clean", Delete::class) {
    delete(rootProject.buildDir)
}

App level:

plugins {
    id("com.android.application")
    id("kotlin-android")
    kotlin("kapt")
    id("dagger.hilt.android.plugin")
    id("io.sentry.android.gradle") version "3.6.0"
    id("com.mikepenz.aboutlibraries.plugin") version "10.6.2"
    id("io.realm.kotlin")
    id("com.google.gms.google-services")
}

android {
    compileSdk = AppConfig.compileSdk

    defaultConfig {
        applicationId = "..."
        minSdk = AppConfig.minSdkVersion
        targetSdk = AppConfig.targetSdkVersion
        versionCode = 1
        versionName = "DEBUG"

        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            isMinifyEnabled = true
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
        debug {
            applicationIdSuffix = Constants.BUILD_TYPE_DEBUG_ID_SUFFIX
            versionNameSuffix = Constants.BUILD_TYPE_DEBUG_VERSION_NAME_SUFFIX
        }
        create(Constants.BUILD_TYPE_BETA) {
            initWith(getByName(Constants.BUILD_TYPE_RELEASE))
            versionNameSuffix = Constants.BUILD_TYPE_BETA_VERSION_NAME_SUFFIX
        }
        create(Constants.BUILD_TYPE_INTERNAL) {
            initWith(getByName(Constants.BUILD_TYPE_RELEASE))
            versionNameSuffix = Constants.BUILD_TYPE_INTERNAL_VERSION_NAME_SUFFIX
        }
    }

    flavorDimensions += "flavor"
    productFlavors {
        create("internalTesting") {
            dimension = "flavor"
            applicationIdSuffix = ".internal"
        }
        create("default") {
            dimension = "flavor"
            isDefault = true
        }
    }

    buildFeatures {
        compose = true
    }
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_17
        targetCompatibility = JavaVersion.VERSION_17
        isCoreLibraryDesugaringEnabled = true
    }
    kotlinOptions {
        jvmTarget = AppConfig.jvmTarget
    }
    composeOptions {
        kotlinCompilerExtensionVersion = "1.4.7"
    }
    namespace = "..."
}

val internalImplementation by configurations
val betaImplementation by configurations

dependencies {
    <dependencies to other modules>

    // bottom sheet dialog
    implementation("com.holix.android:bottomsheetdialog-compose:1.3.0")

    // AboutLibraries
    implementation("com.mikepenz:aboutlibraries-core:10.6.1")
    implementation("com.mikepenz:aboutlibraries-compose:10.6.1")

    // reorderable
    implementation("org.burnoutcrew.composereorderable:reorderable:0.9.6")

    // androidX
    implementation("androidx.constraintlayout:constraintlayout-compose:1.0.1")
    implementation("androidx.core:core-splashscreen:1.0.1")
    implementation("androidx.datastore:datastore-preferences:1.0.0")

    // coil
    implementation("io.coil-kt:coil-compose:2.4.0")

    // Google login
    implementation("com.google.android.gms:play-services-auth:20.5.0")

    // Accompanist
    implementation("com.google.accompanist:accompanist-systemuicontroller:0.28.0")
    implementation("com.google.accompanist:accompanist-webview:0.28.0")

    // Material theme
    implementation("com.google.android.material:material:1.9.0")

    // Desugaring
    coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.3")

    // Hilt
    implementation("com.google.dagger:hilt-android:2.45")
    kapt("com.google.dagger:hilt-compiler:2.45")
    kapt("androidx.hilt:hilt-compiler:1.0.0")

    // Firebase app distribution
    betaImplementation("com.google.firebase:firebase-appdistribution:16.0.0-beta08")

    debugImplementation("com.google.firebase:firebase-appdistribution-api-ktx:16.0.0-beta08")
    internalImplementation("com.google.firebase:firebase-appdistribution-api-ktx:16.0.0-beta08")
    releaseImplementation("com.google.firebase:firebase-appdistribution-api-ktx:16.0.0-beta08")

    // test
    testImplementation("junit:junit:4.13.2")
    androidTestImplementation("androidx.test.ext:junit:1.1.5")
    androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
    androidTestImplementation("com.google.dagger:hilt-android-testing:2.45")
}

kapt {
    correctErrorTypes = true
}
DamianJaeger commented 1 year ago

Note the following dependencies in a module the app module depends on

api("io.realm.kotlin:library-base:1.8.0")
api("io.realm.kotlin:library-sync:1.8.0")
DamianJaeger commented 1 year ago

This seems to be related to waitForInitialRemoteData:

fun App.getUserRealmInstance(): Realm {
    val user = currentUser ?: throw NotLoggedInException()
    val config = SyncConfiguration
        .Builder(
            user = user,
            partitionValue = userPartition(),
            schema = SCHEMA,
        )
        .syncClientResetStrategy(clientResetStrategy)
        .errorHandler(errorHandler)
        .waitForInitialRemoteData() // Removing this line prevents the crash
        .build()

    return Realm.open(config)
}
DamianJaeger commented 1 year ago

I have been able to figure out the following:

There are the entities NotificationsEntity and NotificationItemEntity:

@PersistedName("DBNotificationsEntity")
class NotificationsEntity(
    @PrimaryKey @PersistedName(FIELD_NAME_ID) var id: ObjectId = ObjectId(),
    @PersistedName("_partition") var partition: String = "",
    ...
) : RealmObject {
    constructor() : this(id = ObjectId())
    val notifications: RealmResults<NotificationItemEntity> by backlinks(NotificationItemEntity::notification)
}
@PersistedName("DBNotificationItemEntity")
class NotificationItemEntity(
    @PrimaryKey @PersistedName("_id") var id: ObjectId = ObjectId(),
    @PersistedName("_partition") var partition: String = "",
    @PersistedName("notification") var notification: NotificationsEntity? = null,
    ...
) : RealmObject {
    constructor() : this(id = ObjectId())
}

If waitForInitialRemoteData is used, the aforementioned crash happens. If not, opening the realm fails with

java.lang.IllegalStateException: [RLM_ERR_SCHEMA_VALIDATION_FAILED]: Schema validation failed due to the following errors:
                                                                                 - Property 'DBNotificationItemEntity.notification' of type 'object' has unknown object type 'NotificationsEntity'
                                                                                 - Property 'DBNotificationItemEntity.notification' declared as origin of linking objects property 'DBNotificationsEntity.notifications' links to type 'NotificationsEntity'

After renaming the class NotificationsEntity to DBNotificationsEntity (to match the persisted name), everything works as expected, even when using waitForInitialRemoteData.

cmelchior commented 1 year ago

Thank you for that detailed report @DamianJaeger, we are looking into it.

nicola-cab commented 1 year ago

Has this to be moved to Kotlin? @cmelchior ... Should I move the issue?

cmelchior commented 1 year ago

@nicola-cab It is already moved

cmelchior commented 1 year ago

Hi @DamianJaeger This might be a problem with incremental compilation. Can you reproduce this when doing a full build?

DamianJaeger commented 1 year ago

Yes, I can reproduce this with a clean build. I can reproduce it by renaming any entity class in the project in a similar relationship to not match the name given in the @PersistedName annotation. This leads to a schema validation error when not using waitForInitialRemoteData and the crash when using it.

cmelchior commented 1 year ago

Ah sorry, we identified the problem with errors for waitForInitialRemoteData. It is a bug we will fix shortly.

But we also have found something that needs further investigation, but incremental compilation might not work correctly when using @PersistedName on classes.

The reason is that when you have a Parent -> Child relationship, we use our compiler plugin to embed some information about Child in Parent so when you just refactor Child the metainformation (the class name), is not changed in Parent as the Kotlin compiler do not think it needs to recompile it. We are still looking into it though.

cmelchior commented 1 year ago

Both the bugs you ran into have been fixed in 1.9.1 which has just been released to Maven Central. Sorry for the bad luck of running into two bugs at once.