Kotlin脚本设置constructorArgs触发BasicJvmScriptEvaluator参数不匹配异常
Kotlin脚本设置
constructorArgs时触发参数类型不匹配异常 问题详情
按照Kotlin官方自定义脚本依赖教程开发时一切正常,后续尝试通过constructorArgs将脚本包装到对象中,核心代码如下:
private val config = createJvmCompilationConfigurationFromTemplate<MavenScriptDefinition>() fun evaluate(file: File, scope: Definition): ResultWithDiagnostics<EvaluationResult> { val host = BasicJvmScriptingHost() return host.evalWithTemplate<MavenScriptDefinition>(file.toScriptSource(), evaluation = { this.compilationConfiguration(config) this.constructorArgs(scope) }) }
其中Definition是一个包含greet方法的接口,该方法已实现输出Hello World逻辑。
运行后抛出如下异常:
java.lang.IllegalArgumentException: argument type mismatch at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at kotlin.script.experimental.jvm.BasicJvmScriptEvaluator.evalWithConfigAndOtherScriptsResults(BasicJvmScriptEvaluator.kt:105)
即使将传入对象简化为空对象,异常仍会触发,异常栈指向Kotlin标准类BasicJvmScriptEvaluator.kt内部的构造实例逻辑。完整代码需修改Core文件适配自定义类加载器。
原因分析
该异常的核心是Kotlin脚本引擎生成的脚本类构造器参数,与你通过constructorArgs传入的参数类型/数量不匹配。默认情况下,脚本类的构造器签名可能并未声明接收Definition类型参数,甚至可能无参,导致反射实例化时类型不匹配。
解决方案
- 配置脚本编译参数类型
在创建编译配置时,显式指定脚本类的构造参数类型,确保与传入的scope类型一致:
private val config = createJvmCompilationConfigurationFromTemplate<MavenScriptDefinition> { jvm { constructorParameterTypes.add(Definition::class) } }
- 确保脚本类与
Definition关联
修改脚本定义MavenScriptDefinition,让生成的脚本类实现Definition接口,或者继承包含对应构造参数的基类,确保构造器参数签名匹配。例如在脚本定义中指定基类:
// MavenScriptDefinition相关配置 class MavenScriptDefinition : ScriptDefinition( compilationConfiguration = createJvmCompilationConfigurationFromTemplate<MavenScriptDefinition> { baseClass(Definition::class) // 其他配置... } )
验证类加载一致性
由于需要适配自定义类加载器,需确保Definition类在脚本引擎使用的类加载器中可见,避免因类加载器隔离导致的“相同类但类型不匹配”问题。排查构造器实际签名
若问题仍存在,可通过调试打印脚本类的构造器参数类型,确认实际需求的参数:
// 在异常触发前或调试阶段获取脚本类,打印构造器信息 val scriptClass = ... // 获取生成的脚本Class对象 scriptClass.declaredConstructors.forEach { println("构造器参数类型:${it.parameterTypes.contentToString()}") }
根据打印结果调整constructorArgs的传入参数,确保类型和数量完全匹配。
内容的提问来源于stack exchange,提问作者micartey
相关产品推荐
相关产品推荐

