Reputation: 1515
I'm using moshi which accesses the Kotlin default constructor of a class by reflection.
The class looks like this:
@JsonClass(generateAdapter = true)
data class AClassName(
val threadId: String,
val title: String? = null
)
If I use "View bytecode" in Android Studio I can see the constructor does in fact exist:
public synthetic <init>(Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
To try and keep it I add
-keep @com.squareup.moshi.JsonClass class * {
<init>(...);
}
However, r8 removes it anyway, keeping only the non-synthetic constructor. Does anyone know why?
Upvotes: 1
Views: 504
Reputation: 4628
From what I can see R8 keeps the Kotlin default constructor when using the shown rule. However, it also renames the type kotlin.jvm.internal.DefaultConstructorMarker
, as there is no keep on that class, so after R8 there are the DEX contains the following two constructors:
.method public constructor <init>(Ljava/lang/String;Ljava/lang/String;)V
.method public synthetic constructor <init>(Ljava/lang/String;Ljava/lang/String;ILb/a;)V
Adding -keep
on the marker class
-keep,allowshrinking class kotlin.jvm.internal.DefaultConstructorMarker
results in the following methods in the DEX:
.method public constructor <init>(Ljava/lang/String;Ljava/lang/String;)V
.method public synthetic constructor <init>(Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
Which I assume is what you are looking for.
If there are default values for all properties
data class AClassName(
val threadId: String = "",
val title: String? = null
)
or an explicit empty constructor
data class AClassName(
val threadId: String,
val title: String? = null
) {
constructor() : this("", null)
}
you will also get the Java no-args constructor:
.method public constructor <init>()V
Upvotes: 1