R8 剥离反射所需的 Kotlin 伴随对象
R8 stripping out Kotlin companion object needed for reflection
我有一个 class 带有实现工厂接口的伴随对象。
class GoalInspectorData(
...
) {
companion object : DataClassFactory<GoalInspectorData> {
override fun fromV8Object(v8Object: V8Object): GoalInspectorData {
...
}
}
}
我有一些代码在运行时使用反射检查这个 class 以查看 class 是否提供工厂方法。它通过检查 class 是否有伴生对象 (companionObjectInstance
) 来实现这一点,如果有,则该伴生对象是否实现了工厂接口。
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}")
}
}
这在调试版本中一切正常。
它在启用 R8 的发布版本中失败(minifyEnabled true
in build.gradle)。它失败了,因为 companionObjectInstance
returns null
。
我正在使用 不优化 Proguard 配置:
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
在我自己的 proguard-rules.pro 中,我添加了几乎所有我能想到的 -keep
规则,试图保留这个伴随对象, 并为所有内容添加了 @Keep
注释,但没有任何效果。 R8决心把它剥离出来
例如:
-keep class my.package.** {
*;
}
-keep interface my.package.** {
*;
}
-if class **$Companion extends **
-keep class <2>
-if class **$Companion implements **
-keep class <2>
是否有任何其他 -keep
规则或配置选项可以指示 R8 保留此伴随对象?
首先,保持规则
-keep class my.package.** {
*;
}
应该足以保留所有 classes - 包括程序中的同伴 classes。您不需要 -dontoptimize
标志,因此使用配置 proguard-android-optimize.txt
应该没问题。
但是,当您使用 Kotlin 反射时,您可能还需要使用以下规则保留注释 class kotlin.Metadata
和运行时可见注释:
-keep @interface kotlin.Metadata {
*;
}
-keepattributes RuntimeVisibleAnnotations
如果还是不行,请提交一份 R8 issue 好吗?如果你能包括一个简单的复制品那就太好了。
我有一个 class 带有实现工厂接口的伴随对象。
class GoalInspectorData(
...
) {
companion object : DataClassFactory<GoalInspectorData> {
override fun fromV8Object(v8Object: V8Object): GoalInspectorData {
...
}
}
}
我有一些代码在运行时使用反射检查这个 class 以查看 class 是否提供工厂方法。它通过检查 class 是否有伴生对象 (companionObjectInstance
) 来实现这一点,如果有,则该伴生对象是否实现了工厂接口。
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}")
}
}
这在调试版本中一切正常。
它在启用 R8 的发布版本中失败(minifyEnabled true
in build.gradle)。它失败了,因为 companionObjectInstance
returns null
。
我正在使用 不优化 Proguard 配置:
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
在我自己的 proguard-rules.pro 中,我添加了几乎所有我能想到的 -keep
规则,试图保留这个伴随对象, 并为所有内容添加了 @Keep
注释,但没有任何效果。 R8决心把它剥离出来
例如:
-keep class my.package.** {
*;
}
-keep interface my.package.** {
*;
}
-if class **$Companion extends **
-keep class <2>
-if class **$Companion implements **
-keep class <2>
是否有任何其他 -keep
规则或配置选项可以指示 R8 保留此伴随对象?
首先,保持规则
-keep class my.package.** {
*;
}
应该足以保留所有 classes - 包括程序中的同伴 classes。您不需要 -dontoptimize
标志,因此使用配置 proguard-android-optimize.txt
应该没问题。
但是,当您使用 Kotlin 反射时,您可能还需要使用以下规则保留注释 class kotlin.Metadata
和运行时可见注释:
-keep @interface kotlin.Metadata {
*;
}
-keepattributes RuntimeVisibleAnnotations
如果还是不行,请提交一份 R8 issue 好吗?如果你能包括一个简单的复制品那就太好了。