如何从ScriptEngineManager检索Kotlin jsr223脚本引擎?

时间:2018-10-29 23:52:34

标签: kotlin scripting jsr223 jvm-languages javax.script

我正在尝试编写一个界面(GUI)以运行一些Kotlin脚本。我仅从Junit测试开始,以确保可以执行脚本。我什至无法加载kotlin引擎。看来我的依存关系(等级)是有序的,但是您可以再次检查。

var arr = [1, 2, 3, 4, 5];

var newArr = arr.reduce((acc, current) => {
  acc.push((acc[acc.length - 1] || 0) + current);
  return acc;
}, []);

console.log(newArr);

上方:compile name: 'kotlin-script-runtime', group: 'org.jetbrains.kotlin', version: kotlin_version compile name: 'kotlin-script-util', group: 'org.jetbrains.kotlin', version: kotlin_version compile name: 'kotlin-compiler-embeddable', group: 'org.jetbrains.kotlin', version: kotlin_version

这是测试失败:

ext.kotlin_version = '1.3.0'

最后一个@Test fun testEngine() { // attempt to load script engine class before looking for it val ktsEngineClassName = "org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngine"; var clazz: Class<*>? = null; // assign the clazz variable inside a closure to catch ClassNotFound assertDoesNotThrow({clazz = Class.forName(ktsEngineClassName)}, "could not find $ktsEngineClassName") // just to make sure it's there assertNotNull(clazz, "could not find $ktsEngineClassName") // so far so good, but here's the problem: val engineName = "kotlin" // load the factory val factory = ScriptEngineManager().getEngineByName(engineName)?.factory // and test that we got it assertNotNull(factory, "didn't find factory for '$engineName'." + "\navailable: ${ScriptEngineManager().engineFactories}") } 失败,显示以下输出:

assertNotNull

您可以看到,尽管脚本引擎类似乎已成功通过org.opentest4j.AssertionFailedError: didn't find factory for 'kotlin'. available: [jdk.nashorn.api.scripting.NashornScriptEngineFactory@1a41b1fc] ==> expected: not <null> 加载,但未注册名称Class.forName,并且可用引擎列表仅包含Nashorn。如何确保引擎已注册?

1 个答案:

答案 0 :(得分:1)

看起来kotlin脚本引擎不在默认的类加载器中,因此在实例化ScriptEngineManager时需要指定一个类加载器:

ScriptEngineManager(clazz.getClassLoader()) getEngineByName(engineName)?. factory

更新

在Java 8中,如果您在路径 META_INF / services 中查看 $ JAVA_HOME / jre / lib / ext / nashorn.jar ,会有一个名为的文件> javax.script.ScriptEngineFactory 。内容是:

jdk.nashorn.api.scripting.NashornScriptEngineFactory

因此,当ScriptEngineManager寻找ScriptEngine实现时,它将扫描类路径中名为/META-INF/services/javax.script.ScriptEngineFactory的条目,并从找到的每个条目中加载类名称。

通常,包含目标脚本引擎的jar将包含其自己的服务文件,但是,如果您的kotlin脚本引擎已经在类路径中,我想您可以使用以下命令创建名为/META-INF/services/javax.script.ScriptEngineFactory的类路径资源

的纯文本上下文
org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngineFactory

,您应该很好。另外,您不需要在示例// so far so good, but here's the problem:上方的示例中提供的任何代码。