Crash on app side using sentry, kotlin serialization, and kotlin reflection
sarieh opened this issue · comments
Integration
sentry-android
Build System
Gradle
AGP Version
7.4.2
Proguard
Disabled
Version
3.12.0
Steps to Reproduce
- In the app, there are data classes using Kotlin serialization
- Add sentry plugin into gradle app module,
id ("io.sentry.android.gradle") version "3.12.0"
- Use Kotlin reflection to access data class members
dataClass::class.member
- a crash happens when the following message:
java.lang.AssertionError: Class with incorrect id found: expected .../domain/model/Season.$serializer, actual .../domain/model/Season.serializer
- replace Kotlin serialization with java.io.Serializable, the crash disappears
- or, removing the sentry plugin from the app module also then the crash disappears
Expected Result
The app shouldn't crash when Kotlin serialization is used instead of Java serialization
Actual Result
java.lang.AssertionError: Class with incorrect id found: expected .../domain/model/Season.$serializer, actual .../domain/model/Season.serializer
at kotlin.reflect.jvm.internal.impl.load.kotlin.JavaClassDataFinder.findClassData(JavaClassDataFinder.kt:32)
at kotlin.reflect.jvm.internal.impl.serialization.deserialization.ClassDeserializer.createClass(ClassDeserializer.kt:44)
at kotlin.reflect.jvm.internal.impl.serialization.deserialization.ClassDeserializer.access$createClass(ClassDeserializer.kt:27)
at kotlin.reflect.jvm.internal.impl.serialization.deserialization.ClassDeserializer$classes$1.invoke(ClassDeserializer.kt:29)
at kotlin.reflect.jvm.internal.impl.serialization.deserialization.ClassDeserializer$classes$1.invoke(ClassDeserializer.kt:29)
at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$MapBasedMemoizedFunction.invoke(LockBasedStorageManager.java:578)
at kotlin.reflect.jvm.internal.impl.serialization.deserialization.ClassDeserializer.deserializeClass(ClassDeserializer.kt:34)
at kotlin.reflect.jvm.internal.impl.serialization.deserialization.ClassDeserializer.deserializeClass$default(ClassDeserializer.kt:33)
at kotlin.reflect.jvm.internal.impl.serialization.deserialization.DeserializationComponents.deserializeClass(context.kt:62)
at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedMemberScope.deserializeClass(DeserializedMemberScope.kt:144)
at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedMemberScope.computeDescriptors(DeserializedMemberScope.kt:120)
at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedClassDescriptor$DeserializedClassMemberScope$allDescriptors$1.invoke(DeserializedClassDescriptor.kt:274)
at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedClassDescriptor$DeserializedClassMemberScope$allDescriptors$1.invoke(DeserializedClassDescriptor.kt:273)
at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$LockBasedLazyValue.invoke(LockBasedStorageManager.java:408)
at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$LockBasedNotNullLazyValue.invoke(LockBasedStorageManager.java:527)
at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedClassDescriptor$DeserializedClassMemberScope.getContributedDescriptors(DeserializedClassDescriptor.kt:284)
at kotlin.reflect.jvm.internal.impl.resolve.scopes.ResolutionScope$DefaultImpls.getContributedDescriptors$default(ResolutionScope.kt:50)
at kotlin.reflect.jvm.internal.KDeclarationContainerImpl.getMembers(KDeclarationContainerImpl.kt:56)
at kotlin.reflect.jvm.internal.KClassImpl$Data$declaredNonStaticMembers$2.invoke(KClassImpl.kt:162)
at kotlin.reflect.jvm.internal.KClassImpl$Data$declaredNonStaticMembers$2.invoke(KClassImpl.kt:162)
at kotlin.reflect.jvm.internal.ReflectProperties$LazySoftVal.invoke(ReflectProperties.java:93)
at kotlin.reflect.jvm.internal.ReflectProperties$Val.getValue(ReflectProperties.java:32)
at kotlin.reflect.jvm.internal.KClassImpl$Data.getDeclaredNonStaticMembers(KClassImpl.kt:162)
at kotlin.reflect.jvm.internal.KClassImpl$Data$allNonStaticMembers$2.invoke(KClassImpl.kt:171)
at kotlin.reflect.jvm.internal.KClassImpl$Data$allNonStaticMembers$2.invoke(KClassImpl.kt:171)
at kotlin.reflect.jvm.internal.ReflectProperties$LazySoftVal.invoke(ReflectProperties.java:93)
at kotlin.reflect.jvm.internal.ReflectProperties$Val.getValue(ReflectProperties.java:32)
at kotlin.reflect.jvm.internal.KClassImpl$Data.getAllNonStaticMembers(KClassImpl.kt:171)
at kotlin.reflect.jvm.internal.KClassImpl$Data$allMembers$2.invoke(KClassImpl.kt:177)
at kotlin.reflect.jvm.internal.KClassImpl$Data$allMembers$2.invoke(KClassImpl.kt:177)
at kotlin.reflect.jvm.internal.ReflectProperties$LazySoftVal.invoke(ReflectProperties.java:93)
@romtsn here is a simple sample project https://github.com/sarieh/AndroidSentrySample
I created a new project and added the related code as follows:
- Added sentry plugin
- Added Kotlin serialization and Kotlin reflection libraries
- Used Kotlin reflection with a data class using the Kotlin serialization -> resulting in a crash
- remove sentry plugin, retry step 3 -> no crash
@sarieh thanks a lot for the MRE, we'll investigate!
I was able to reproduce it locally, thanks @sarieh for the MRE, it's very good! Looks like the culprit is our FileIO instrumentation, because when I add these lines to the gradle config, it works fine
sentry {
tracingInstrumentation {
features.set(setOf(DATABASE, OKHTTP, COMPOSE))
}
}
@sarieh you can use this as a workaround for now until we fix it on our side. Thank you!
This seems to be the underlying fix required: https://gitlab.ow2.org/asm/asm/-/merge_requests/363
@sarieh looks like if you update AGP (8.3.0-beta02
though), the issue will fix itself because they've updated the ASM version to 9.6.:
We're still considering fixing it on our side though!