You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin混淆后KFunction.callBy报错:需2参数却传1(DefaultConstructorMarker问题)

问题

在开启代码混淆的Kotlin环境里,用KFunction.callBy动态调用构造函数时出问题了:没开混淆时代码正常运行,一开混淆就报错,错误信息是Callable expects 2 arguments, but 1 were provided。排查后发现,constructor.caller.parameterTypes里多出来一个DefaultConstructorMarker类型的参数。

代码示例

data class User(
    val name: String
)

private fun <T> buildObject(
    ...
    constructor: KFunction<T>,
): T {
    val params = constructor.valueParameters.mapIndexed { index, param ->
        val res = getValueForParam()
        param to res
    }.toMap()
    return constructor.callBy(params)
}

报错信息

Callable expects 2 arguments, but 1 were provided

当前使用的ProGuard规则

-keepattributes *Annotation*, Signature, InnerClasses, Synthetic, MethodParameters, RuntimeVisibleAnnotations, RuntimeVisibleParameterAnnotations, Record, InnerClasses, EnclosingMethod
-keep class my.package.** { *;<init>(...); }
-keepclassmembers class my.package.**$* { *; }
-keepclassmembernames class my.package.**$* { *; }
-keep class kotlin.Metadata { *; }

解决方案

问题根源是混淆过程中,Kotlin编译自动生成的带DefaultConstructorMarker参数的合成构造函数元数据被破坏,导致KFunction错把这个内部专用参数当成了需要手动传入的普通参数。

调整ProGuard规则,补充以下内容:

# 保留目标包下类的构造函数及参数信息,避免合成构造函数元数据丢失
-keepclassmembers class my.package.** {
    <init>(...);
    @kotlin.jvm.JvmOverloads <init>(...);
}
# 保留Kotlin内部的DefaultConstructorMarker类,禁止混淆工具修改或移除它
-keep class kotlin.jvm.internal.DefaultConstructorMarker { *; }
# 确保Kotlin反射所需的元数据完整保留
-keepattributes KotlinMetadata

另外注意:原规则里的-keepattributes已经包含Synthetic,但部分版本的ProGuard需要显式指定KotlinMetadata属性,才能保证Kotlin反射依赖的元数据不被混淆破坏。

内容的提问来源于stack exchange,提问作者NonceWizard

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 21:13:25