Simplify and fix classloaders handling on script evaluation

#KT-37558 fixed
This commit is contained in:
Ilya Chernikov
2020-04-02 18:58:40 +02:00
parent 138efda19f
commit f84fd810f0
5 changed files with 135 additions and 78 deletions
@@ -8,11 +8,8 @@ package kotlin.script.experimental.jvmhost
import java.io.File
import java.net.URLClassLoader
import java.util.jar.JarInputStream
import kotlin.script.experimental.api.CompiledScript
import kotlin.script.experimental.api.ScriptCompilationConfiguration
import kotlin.script.experimental.api.SourceCode
import kotlin.script.experimental.api.hostConfiguration
import kotlin.script.experimental.host.ScriptingHostConfiguration
import kotlin.reflect.KClass
import kotlin.script.experimental.api.*
import kotlin.script.experimental.jvm.CompiledJvmScriptsCache
import kotlin.script.experimental.jvm.baseClassLoader
import kotlin.script.experimental.jvm.impl.KJvmCompiledScript
@@ -33,12 +30,7 @@ open class CompiledScriptJarsCache(val scriptToFile: (SourceCode, ScriptCompilat
it.manifest.mainAttributes.getValue("Main-Class")
}
}
val classLoader = URLClassLoader(
arrayOf(file.toURI().toURL()),
scriptCompilationConfiguration[ScriptCompilationConfiguration.hostConfiguration]?.get(ScriptingHostConfiguration.jvm.baseClassLoader)
)
return createScriptFromClassLoader(className, classLoader)
return KJvmCompiledScriptLazilyLoadedFromClasspath(className, listOf(file))
}
override fun store(
@@ -54,4 +46,40 @@ open class CompiledScriptJarsCache(val scriptToFile: (SourceCode, ScriptCompilat
jvmScript.saveToJar(file)
}
}
}
private class KJvmCompiledScriptLazilyLoadedFromClasspath(
private val scriptClassFQName: String,
private val classPath: List<File>
) : CompiledScript {
private var loadedScript: KJvmCompiledScript? = null
fun getScriptOrError(): KJvmCompiledScript = loadedScript ?: throw RuntimeException("Compiled script is not loaded yet")
override suspend fun getClass(scriptEvaluationConfiguration: ScriptEvaluationConfiguration?): ResultWithDiagnostics<KClass<*>> {
if (loadedScript == null) {
val actualEvaluationConfiguration = scriptEvaluationConfiguration ?: ScriptEvaluationConfiguration()
val baseClassLoader = actualEvaluationConfiguration[ScriptEvaluationConfiguration.jvm.baseClassLoader]
val classLoader = URLClassLoader(
classPath.map { it.toURI().toURL() }.toTypedArray(),
baseClassLoader
)
loadedScript = createScriptFromClassLoader(scriptClassFQName, classLoader)
}
return getScriptOrError().getClass(scriptEvaluationConfiguration)
}
override val compilationConfiguration: ScriptCompilationConfiguration
get() = getScriptOrError().compilationConfiguration
override val sourceLocationId: String?
get() = getScriptOrError().sourceLocationId
override val otherScripts: List<CompiledScript>
get() = getScriptOrError().otherScripts
override val resultField: Pair<String, KotlinType>?
get() = getScriptOrError().resultField
}
@@ -14,7 +14,6 @@ import java.util.jar.Manifest
import kotlin.script.experimental.api.*
import kotlin.script.experimental.jvm.JvmDependency
import kotlin.script.experimental.jvm.impl.*
import kotlin.script.experimental.jvm.util.scriptCompilationClasspathFromContext
import kotlin.script.experimental.jvm.util.scriptCompilationClasspathFromContextOrNull
// TODO: generate execution code (main)