We upgraded to Kotlin 1.2 but got warnings at compile time and crashes at runtime. This is a ProGuard config change makes the app working again.
-dontwarn kotlin.reflect.jvm.internal.**
-keep class kotlin.reflect.jvm.internal.** { *; }
Hesitant to submit a PR just yet because I didn't spend too much time to see if this is the minimum config to get it working with kotlin 1.2. The crashes were reported very late night so I just quickly made a hotfix.
Posted here in case someone else has this issue. Or someone is more familiar with the changes can shed some light on this. I might find some time tomorrow digging deeper into this.
The warnings were:
Warning: kotlin.reflect.jvm.internal.KClassImpl: can't find referenced class kotlin.reflect.jvm.internal.KClassImpl$kotlin.reflect.jvm.internal.KClassImpl$Data
Warning: kotlin.reflect.jvm.internal.KClassImpl: can't find referenced class kotlin.reflect.jvm.internal.KClassImpl$kotlin.reflect.jvm.internal.KClassImpl$Data
Warning: kotlin.reflect.jvm.internal.KClassImpl$data$1: can't find referenced class kotlin.reflect.jvm.internal.KClassImpl$kotlin.reflect.jvm.internal.KClassImpl$Data
Warning: kotlin.reflect.jvm.internal.KClassImpl$data$1: can't find referenced class kotlin.reflect.jvm.internal.KClassImpl$kotlin.reflect.jvm.internal.KClassImpl$Data
Warning: kotlin.reflect.jvm.internal.impl.protobuf.SmallSortedMap: can't find referenced class kotlin.reflect.jvm.internal.impl.protobuf.SmallSortedMap$kotlin.reflect.jvm.internal.impl.protobuf.SmallSortedMap$Entry
Warning: kotlin.reflect.jvm.internal.impl.protobuf.SmallSortedMap: can't find referenced class kotlin.reflect.jvm.internal.impl.protobuf.SmallSortedMap$kotlin.reflect.jvm.internal.impl.protobuf.SmallSortedMap$EntrySet
Warning: kotlin.reflect.jvm.internal.impl.protobuf.SmallSortedMap$Entry: can't find referenced class kotlin.reflect.jvm.internal.impl.protobuf.SmallSortedMap$kotlin.reflect.jvm.internal.impl.protobuf.SmallSortedMap$Entry
Warning: kotlin.reflect.jvm.internal.impl.protobuf.SmallSortedMap$Entry: can't find referenced class kotlin.reflect.jvm.internal.impl.protobuf.SmallSortedMap$kotlin.reflect.jvm.internal.impl.protobuf.SmallSortedMap$Entry
And the stacktrace for the crashes:
Fatal Exception: java.lang.NoClassDefFoundError: kotlin.reflect.jvm.internal.impl.builtins.b
at kotlin.reflect.jvm.internal.impl.builtins.KotlinBuiltIns.createBuiltInsModule(KotlinBuiltIns.java:150)
at kotlin.reflect.jvm.internal.impl.platform.JvmBuiltIns.(JvmBuiltIns.kt)
at kotlin.reflect.jvm.internal.impl.platform.JvmBuiltIns.(JvmBuiltIns.kt)
at kotlin.reflect.jvm.internal.impl.load.kotlin.reflect.RuntimeModuleData$Companion.create(RuntimeModuleData.kt:54)
at kotlin.reflect.jvm.internal.ModuleByClassLoaderKt.getOrCreateModule(moduleByClassLoader.kt:58)
at kotlin.reflect.jvm.internal.KDeclarationContainerImpl$Data$moduleData$2.invoke(KDeclarationContainerImpl.kt:35)
at kotlin.reflect.jvm.internal.KDeclarationContainerImpl$Data$moduleData$2.invoke(KDeclarationContainerImpl.kt:32)
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.KDeclarationContainerImpl$Data.getModuleData(KDeclarationContainerImpl.kt)
at kotlin.reflect.jvm.internal.KClassImpl$Data$descriptor$2.invoke(KClassImpl.kt:46)
at kotlin.reflect.jvm.internal.KClassImpl$Data$descriptor$2.invoke(KClassImpl.kt:43)
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.getDescriptor(KClassImpl.kt)
at kotlin.reflect.jvm.internal.KClassImpl.getDescriptor(KClassImpl.kt:172)
at kotlin.reflect.jvm.internal.KClassImpl.getConstructorDescriptors(KClassImpl.kt:186)
at kotlin.reflect.jvm.internal.KClassImpl$Data$constructors$2.invoke(KClassImpl.kt:90)
at kotlin.reflect.jvm.internal.KClassImpl$Data$constructors$2.invoke(KClassImpl.kt:43)
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.getConstructors(KClassImpl.kt)
at kotlin.reflect.jvm.internal.KClassImpl.getConstructors(KClassImpl.kt:222)
at kotlin.reflect.full.KClasses.getPrimaryConstructor(KClasses.kt:40)
at com.squareup.moshi.KotlinJsonAdapterFactory.create(KotlinJsonAdapter.kt:160)
at com.squareup.moshi.Moshi.adapter(Moshi.java:100)
at retrofit2.converter.moshi.MoshiConverterFactory.responseBodyConverter(MoshiConverterFactory.java:91)
at retrofit2.Retrofit.nextResponseBodyConverter(Retrofit.java:330)
at retrofit2.Retrofit.responseBodyConverter(Retrofit.java:313)
at retrofit2.ServiceMethod$Builder.createResponseConverter(ServiceMethod.java:736)
at retrofit2.ServiceMethod$Builder.build(ServiceMethod.java:169)
at retrofit2.Retrofit.loadServiceMethod(Retrofit.java:170)
at retrofit2.Retrofit$1.invoke(Retrofit.java:147)
and,
Caused by java.util.NoSuchElementException: Collection is empty.
at kotlin.collections.CollectionsKt___CollectionsKt.first(_Collections.kt:166)
at kotlin.reflect.jvm.internal.impl.builtins.BuiltInsLoader$Companion.(BuiltInsLoader.kt)
at kotlin.reflect.jvm.internal.impl.builtins.BuiltInsLoader.(Unknown Source)
at kotlin.reflect.jvm.internal.impl.builtins.KotlinBuiltIns.createBuiltInsModule(KotlinBuiltIns.java:150)
at kotlin.reflect.jvm.internal.impl.platform.JvmBuiltIns.(JvmBuiltIns.kt)
at kotlin.reflect.jvm.internal.impl.platform.JvmBuiltIns.(JvmBuiltIns.kt)
at kotlin.reflect.jvm.internal.impl.load.kotlin.reflect.RuntimeModuleData$Companion.create(RuntimeModuleData.kt:54)
at kotlin.reflect.jvm.internal.ModuleByClassLoaderKt.getOrCreateModule(moduleByClassLoader.kt:58)
at kotlin.reflect.jvm.internal.KDeclarationContainerImpl$Data$moduleData$2.invoke(KDeclarationContainerImpl.kt:35)
at kotlin.reflect.jvm.internal.KDeclarationContainerImpl$Data$moduleData$2.invoke(KDeclarationContainerImpl.kt:32)
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.KDeclarationContainerImpl$Data.getModuleData(Unknown Source:7)
at kotlin.reflect.jvm.internal.KClassImpl$Data$descriptor$2.invoke(KClassImpl.kt:46)
at kotlin.reflect.jvm.internal.KClassImpl$Data$descriptor$2.invoke(KClassImpl.kt:43)
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.getDescriptor(Unknown Source:7)
at kotlin.reflect.jvm.internal.KClassImpl.getDescriptor(KClassImpl.kt:172)
at kotlin.reflect.jvm.internal.KClassImpl.getConstructorDescriptors(KClassImpl.kt:186)
at kotlin.reflect.jvm.internal.KClassImpl$Data$constructors$2.invoke(KClassImpl.kt:90)
at kotlin.reflect.jvm.internal.KClassImpl$Data$constructors$2.invoke(KClassImpl.kt:43)
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.getConstructors(Unknown Source:7)
at kotlin.reflect.jvm.internal.KClassImpl.getConstructors(KClassImpl.kt:222)
at kotlin.reflect.full.KClasses.getPrimaryConstructor(KClasses.kt:40)
at com.squareup.moshi.KotlinJsonAdapterFactory.create(KotlinJsonAdapter.kt:160)
at com.squareup.moshi.Moshi.adapter(Moshi.java:100)
at com.squareup.moshi.Moshi.adapter(Moshi.java:58)
at com.squareup.moshi.CollectionJsonAdapter.newArrayListAdapter(CollectionJsonAdapter.java:52)
at com.squareup.moshi.CollectionJsonAdapter$1.create(CollectionJsonAdapter.java:36)
at com.squareup.moshi.Moshi.adapter(Moshi.java:100)
at com.squareup.moshi.Moshi.adapter(Moshi.java:58)
at com.tinder.api.model.common.AutoValue_ApiMatch$MoshiJsonAdapter.(AutoValue_ApiMatch.java)
at com.tinder.api.model.common.ApiMatch.jsonAdapter(ApiMatch.java:19)
at com.tinder.api.moshi.AutoValueMoshi_TinderMoshiAdapterFactory.create(AutoValueMoshi_TinderMoshiAdapterFactory.java:220)
at com.squareup.moshi.Moshi.adapter(Moshi.java:100)
at com.squareup.moshi.Moshi.adapter(Moshi.java:58)
at com.squareup.moshi.CollectionJsonAdapter.newArrayListAdapter(CollectionJsonAdapter.java:52)
at com.squareup.moshi.CollectionJsonAdapter$1.create(CollectionJsonAdapter.java:36)
at com.squareup.moshi.Moshi.adapter(Moshi.java:100)
at com.squareup.moshi.Moshi.adapter(Moshi.java:58)
at com.tinder.api.model.updates.AutoValue_Updates$MoshiJsonAdapter.(AutoValue_Updates.java)
at com.tinder.api.model.updates.Updates.jsonAdapter(Updates.java:20)
at com.tinder.api.moshi.AutoValueMoshi_TinderMoshiAdapterFactory.create(AutoValueMoshi_TinderMoshiAdapterFactory.java:170)
at com.squareup.moshi.Moshi.adapter(Moshi.java:100)
at retrofit2.converter.moshi.MoshiConverterFactory.responseBodyConverter(MoshiConverterFactory.java:91)
at retrofit2.Retrofit.nextResponseBodyConverter(Retrofit.java:330)
at retrofit2.Retrofit.responseBodyConverter(Retrofit.java:313)
at retrofit2.ServiceMethod$Builder.createResponseConverter(ServiceMethod.java:736)
at retrofit2.ServiceMethod$Builder.build(ServiceMethod.java:169)
at retrofit2.Retrofit.loadServiceMethod(Retrofit.java:170)
at retrofit2.Retrofit$1.invoke(Retrofit.java:147)
at java.lang.reflect.Proxy.invoke(Proxy.java:913)
Finally got some time looking a little deeper into this.
The ProGuard warning actually wasn't coming from the usage of kotlin reflect in moshi kotlin, but rather kotlin reflect 1.2. We explicitly added kotlin reflect 1.2 because of the Runtime JAR files in the classpath should have the same version warning. Though, the kotlin reflect is only used in moshi kotlin, so we can just ignore the warning?
Now the NoClassDefFoundError crashes may just be API changes in 1.2. And the following NoSuchElementException could just be the cascading effect of the NoClassDefFoundError? Played around with different ProGuard configurations and it looks like -keep public class kotlin.reflect.jvm.internal.impl.builtins.* { public *; } is the minimum config to get the app working.
So maybe a PR to update README on ProGuard configuration with kotlin reflect 1.2?
exactly same problem here. I just ignore the warning because if i explicitly add 1.2, it breaks my release build with those warnings.
FWIW - I got a similar trace from running the lint driver in android tools from the CLI. Posted to lint-dev, maybe Tor can shed more light - https://groups.google.com/forum/#!topic/lint-dev/70j4pQ8uMuA
Same crash here. Does anybody have any idea why explicitly adding kotlin-reflect as a dependency causes this crash?
Same issue, have any update info about it?
Same issue here. Watching on this.
i don't have an update on this proguard issue per se. but we are in the process of migrating reflection based moshi kotlin to the codegen. haven't had any horror proguard stories keep me awake at night.
The minimum config is
-keep class kotlin.reflect.jvm.internal.impl.builtins.BuiltInsLoaderImpl
which will keep only the no-arg constructor of the service defined in META-INF/services/kotlin.reflect.jvm.internal.impl.builtins.BuiltInsLoader. Anything more is keeping too much.
I might missed something, but there is no kotlin.reflect.jvm.internal.impl.builtins.BuiltInsLoaderImpl
full name is kotlin.reflect.jvm.internal.impl.serialization.deserialization.builtins.BuiltInsLoaderImpl
and still, this results in various errors of missing FieldOverridabilityCondition, etc
I had the same problem with Kotlin1.3, possible solution is to add this rule.
-keep interface kotlin.reflect.jvm.internal.impl.builtins.BuiltInsLoader
This seems to work (kotlin 1.2.71)
-keep interface kotlin.reflect.jvm.internal.impl.builtins.BuiltInsLoader
-keep class kotlin.reflect.jvm.internal.impl.serialization.deserialization.builtins.BuiltInsLoaderImpl
This work for me (kotlin 1.3.10)
-keep interface kotlin.reflect.jvm.internal.impl.builtins.BuiltInsLoader
-keep class kotlin.reflect.jvm.internal.impl.serialization.deserialization.builtins.BuiltInsLoaderImpl
I might missed something, but there is no
kotlin.reflect.jvm.internal.impl.builtins.BuiltInsLoaderImpl
full name iskotlin.reflect.jvm.internal.impl.serialization.deserialization.builtins.BuiltInsLoaderImpland still, this results in various errors of missing
FieldOverridabilityCondition, etc
same error
-ignorewarnings?
@androidovshchik no because your code will crash in the runtime :)
As of latest kotlin-stdlib (right now 1.3.41 but still uses kotlin-reflect 1.2.71) _I think_ the minimum configuration should change to the following:
-keep class kotlin.reflect.jvm.internal.impl.builtins.BuiltInsLoader
-keep class kotlin.reflect.jvm.internal.impl.serialization.deserialization.builtins.BuiltInsLoaderImpl
-keep class kotlin.reflect.jvm.internal.impl.load.java.FieldOverridabilityCondition
-keep class kotlin.reflect.jvm.internal.impl.load.java.ErasedOverridabilityCondition
-keep class kotlin.reflect.jvm.internal.impl.load.java.JavaIncompatibilityRulesOverridabilityCondition
I still don't understand why the first rule (with the explicit path) works but not this one:
-keep class kotlin.reflect.jvm.internal.impl.builtins. BuiltInsLoaderImpl
which is in the META-INF/services 馃
And as in #880 this:~
-keep class kotlin.Metadata
I think this is something that should be handled in kotlin-reflect's artifact directly, as manually having to figure out which internal APIs of it to keep are just going to potentially break again between kotlin versions (regardless of Moshi version). Would welcome a link to a youtrack issue for Kotlin's issue tracker here.
After talking with Jetbrains on the kotlin-lang slack, I've opened a PR to add embedded proguard rules to kotlin-reflect here: https://github.com/JetBrains/kotlin/pull/2893
Please feel free to chime in with any suggestions!
Most helpful comment
Finally got some time looking a little deeper into this.
The ProGuard warning actually wasn't coming from the usage of kotlin reflect in moshi kotlin, but rather kotlin reflect 1.2. We explicitly added kotlin reflect 1.2 because of the
Runtime JAR files in the classpath should have the same versionwarning. Though, the kotlin reflect is only used in moshi kotlin, so we can just ignore the warning?Now the
NoClassDefFoundErrorcrashes may just be API changes in 1.2. And the followingNoSuchElementExceptioncould just be the cascading effect of theNoClassDefFoundError? Played around with different ProGuard configurations and it looks like-keep public class kotlin.reflect.jvm.internal.impl.builtins.* { public *; }is the minimum config to get the app working.So maybe a PR to update README on ProGuard configuration with kotlin reflect 1.2?