From 956bcf6d7ab69f119d08c659debaa5b75df53611 Mon Sep 17 00:00:00 2001 From: Ilya Chernikov Date: Wed, 4 May 2016 12:43:50 +0200 Subject: [PATCH] Fix permgen problems with script launching by avoiding reflection as much as possible --- .../compiler/KotlinToJVMBytecodeCompiler.kt | 22 +++++++++++-------- .../jetbrains/kotlin/scripts/ScriptTest.kt | 8 +++---- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt index c66c1ea12f2..cc99e9177d5 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt @@ -225,9 +225,8 @@ object KotlinToJVMBytecodeCompiler { try { try { - tryConstructClass(scriptClass.kotlin, scriptArgs) - ?: throw RuntimeException("unable to find appropriate constructor for class ${scriptClass.name} accepting arguments $scriptArgs\n" + - "\tconstructors: \n\t\t${scriptClass.kotlin.constructors.joinToString("\n\t\t", "(") { it.parameters.joinToString { it.type.toString() } }}") + tryConstructClass(scriptClass, scriptArgs) + ?: throw RuntimeException("unable to find appropriate constructor for class ${scriptClass.name} accepting arguments $scriptArgs\n") } finally { // NB: these lines are required (see KT-9546) but aren't covered by tests @@ -260,9 +259,9 @@ object KotlinToJVMBytecodeCompiler { } @TestOnly - fun tryConstructClassPub(scriptClass: KClass, scriptArgs: List): Any? = tryConstructClass(scriptClass, scriptArgs) + fun tryConstructClassPub(scriptClass: Class<*>, scriptArgs: List): Any? = tryConstructClass(scriptClass, scriptArgs) - private fun tryConstructClass(scriptClass: KClass, scriptArgs: List): Any? { + private fun tryConstructClass(scriptClass: Class<*>, scriptArgs: List): Any? { fun convertPrimitive(type: KType?, arg: String): Any? = when (type) { @@ -312,10 +311,15 @@ object KotlinToJVMBytecodeCompiler { return state } - for (ctor in scriptClass.constructors) { - val (ctorArgs, scriptArgsLeft) = ctor.parameters.fold(Pair(emptyList(), scriptArgs), ::foldingFunc) - if (ctorArgs.size == ctor.parameters.size && (scriptArgsLeft == null || scriptArgsLeft.isEmpty())) - return ctor.call(*ctorArgs.toTypedArray()) + try { + return scriptClass.getConstructor(Array::class.java).newInstance(*arrayOf(scriptArgs.toTypedArray())) + } + catch (e: java.lang.NoSuchMethodException) { + for (ctor in scriptClass.kotlin.constructors) { + val (ctorArgs, scriptArgsLeft) = ctor.parameters.fold(Pair(emptyList(), scriptArgs), ::foldingFunc) + if (ctorArgs.size == ctor.parameters.size && (scriptArgsLeft == null || scriptArgsLeft.isEmpty())) + return ctor.call(*ctorArgs.toTypedArray()) + } } return null } diff --git a/compiler/tests/org/jetbrains/kotlin/scripts/ScriptTest.kt b/compiler/tests/org/jetbrains/kotlin/scripts/ScriptTest.kt index 2ae18cf276a..97865e240e7 100644 --- a/compiler/tests/org/jetbrains/kotlin/scripts/ScriptTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/scripts/ScriptTest.kt @@ -53,7 +53,7 @@ class ScriptTest { fun testStandardScriptWithParams() { val aClass = compileScript("fib_std.kts", StandardScriptDefinition) Assert.assertNotNull(aClass) - val anObj = KotlinToJVMBytecodeCompiler.tryConstructClassPub(aClass!!.kotlin, listOf("4", "comment")) + val anObj = KotlinToJVMBytecodeCompiler.tryConstructClassPub(aClass!!, listOf("4", "comment")) Assert.assertNotNull(anObj) } @@ -61,7 +61,7 @@ class ScriptTest { fun testStandardScriptWithoutParams() { val aClass = compileScript("fib_std.kts", StandardScriptDefinition) Assert.assertNotNull(aClass) - val anObj = KotlinToJVMBytecodeCompiler.tryConstructClassPub(aClass!!.kotlin, emptyList()) + val anObj = KotlinToJVMBytecodeCompiler.tryConstructClassPub(aClass!!, emptyList()) Assert.assertNotNull(anObj) } @@ -69,7 +69,7 @@ class ScriptTest { fun testScriptWithParamConversion() { val aClass = compileScript("fib.kts", SimpleParamsTestScriptDefinition(".kts", numIntParam())) Assert.assertNotNull(aClass) - val anObj = KotlinToJVMBytecodeCompiler.tryConstructClassPub(aClass!!.kotlin, listOf("4")) + val anObj = KotlinToJVMBytecodeCompiler.tryConstructClassPub(aClass!!, listOf("4")) Assert.assertNotNull(anObj) } @@ -138,7 +138,7 @@ class ScriptTest { Assert.assertNotNull(aClass) var exceptionThrown = false try { - KotlinToJVMBytecodeCompiler.tryConstructClassPub(aClass!!.kotlin, emptyList()) + KotlinToJVMBytecodeCompiler.tryConstructClassPub(aClass!!, emptyList()) } catch (e: InvocationTargetException) { Assert.assertTrue(e.cause is IllegalStateException)