mardi 17 septembre 2019

R8 stripping out Kotlin companion object needed for reflection

I have a class with a companion object which implements a factory interface.

class GoalInspectorData(
    ...
) {

    companion object : DataClassFactory<GoalInspectorData> {

        override fun fromV8Object(v8Object: V8Object): GoalInspectorData {
            ...
        }
    }
}

I have some code which examines this class at runtime using reflection to see if the class provides a factory method. It does this by checking to see if the class has a companion object (companionObjectInstance) and, if so, if that companion object implements the factory interface.

internal inline fun <reified T> convert(obj: Any): T {

    val companionObject = T::class.companionObjectInstance

    @Suppress("UNCHECKED_CAST")
    return when {
        T::class in builtInClasses -> obj as T
        companionObject as? DataClassFactory<T> != null -> companionObject.fromV8Object(obj as V8Object)
        else -> throw IllegalArgumentException("No converter for type ${T::class}")
    }
}

This all works fine in a debug build.

It fails in a release build with R8 enabled (minifyEnabled true in build.gradle). It fails because companionObjectInstance returns null.

I'm using the "don't optimize" Proguard config:

proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

and in my own proguard-rules.pro I've added just about every -keep rule I can imagine in an attempt to retain this companion object, but nothing works. R8 is determined to strip it out.

For example:

-keep class my.package.** {
    *;
}
-keep interface my.package.** {
    *;
}

-if class **$Companion extends **
-keep class <2>
-if class **$Companion implements **
-keep class <2>

Are there any other -keep rules or configuration options which would instruct R8 to retain this companion object?





Aucun commentaire:

Enregistrer un commentaire