GraalJS - 无法从 jar 构建 ScriptEngine

GraalJS - Cannot build ScriptEngine from jar

我遇到了一个涉及 GraalJS 的问题。我正在尝试将其用作我的 JavaScript 后端。当我从 IntelliJ 中 运行 时,它可以完美地工作,但是一旦我导出 运行nable .jar,它就会停止工作。我已经调试这个问题几天了,以下是我的发现。

应该提到的是,我通过使用 gradle 命令生成我的 运行nable .jar,该命令与 libGdx 一起打包,名为 desktop:dist.

首先,这些是我使用的依赖项

// GraalVM
    compile group: 'org.graalvm.js', name: 'js', version: '20.2.0'
    compile group: 'org.graalvm.js', name: 'js-scriptengine', version: '20.2.0'
    compile group: 'org.graalvm.sdk', name: 'graal-sdk', version: '20.2.0'
    compile group: 'org.graalvm.truffle', name: 'truffle-api', version: '20.2.0'
    implementation 'com.ibm.icu:icu4j:51.1'

这就是我构建 ScriptEngine 的方式

private fun getGraalEngine() = GraalJSScriptEngine.create(
    Engine.newBuilder()
        .allowExperimentalOptions(false)
        .useSystemProperties(false)
        .build(),
    Context.newBuilder("js")
        .allowHostAccess(HostAccess.ALL)
        .allowHostClassLookup { true }
        .allowAllAccess(true))

现在,当我 运行 来自 .jar 的程序时,我得到这个异常:

java.lang.IllegalArgumentException: Could not find option with name js.script-engine-global-scope-import.
    at com.oracle.truffle.polyglot.PolyglotEngineException.illegalArgument(PolyglotEngineException.java:128)
    at com.oracle.truffle.polyglot.OptionValuesImpl.failNotFound(OptionValuesImpl.java:283)
    at com.oracle.truffle.polyglot.PolyglotContextConfig.findLanguageForOption(PolyglotContextConfig.java:239)
    at com.oracle.truffle.polyglot.PolyglotContextConfig.<init>(PolyglotContextConfig.java:129)
    at com.oracle.truffle.polyglot.PolyglotEngineImpl.createContext(PolyglotEngineImpl.java:1434)
    at org.graalvm.polyglot.Context$Builder.build(Context.java:1598)

经过一些调试,我得出的结论是当 PolyglotContextConfig 试图为选项名称 js 找到 PolyglotLanguage 时会发生这种情况。事实证明,这是 IntelliJ 和来自 运行nable .jar 的 运行ning 之间的区别。 IntelliJ 包含对 JavaScript PolyglotLanguage 的支持,而 .jar 不支持。这是我发现的

通过查看 Engine -> impl -> idToLanguage(我通过反射访问了这些包私有字段)我得到以下结果

Intellij :

id to lang: {regex=PolyglotLanguage [id=regex, name=REGEX, host=false], js=PolyglotLanguage [id=js, name=JavaScript, host=false]}

可运行.jar:

id to lang: {regex=PolyglotLanguage [id=regex, name=REGEX, host=false]}

原来对 JavaScript 的支持只是……未命中? 因此,当 PolyglotContextConfig.findLanguageForOption() 尝试将 js optionName 与 JavaScript PolyglotLanguage 匹配时,会发生异常。

我不确定如何进行或为什么会发生这种情况。也许是关于类加载器的?无论哪种方式,我们都将不胜感激

以下link回答了我的问题:https://github.com/oracle/graaljs/issues/125

事实证明,在 .jar 打包过程中,REGEX 和 Javascript 的 PolyglotLanguage 条目以某种方式被覆盖。这意味着您必须在 META-INF/truffle/language 处的 .jar 中创建一个文件,并添加答案中的内容。请注意,对我来说 github link 中的内容 完全 没用。我需要将它们更改为

#https://github.com/graalvm/graaljs/issues/125

language2.characterMimeType.0=application/javascript
language2.characterMimeType.1=application/javascript+module
language2.characterMimeType.2=text/javascript
language2.className=com.oracle.truffle.js.lang.JavaScriptLanguage
language2.defaultMimeType=application/javascript
language2.dependentLanguage.0=regex
language2.fileTypeDetector0=com.oracle.truffle.js.lang.JSFileTypeDetector
language2.id=js
language2.implementationName=GraalVM JavaScript
language2.interactive=true
language2.internal=false
language2.name=JavaScript
language2.version=inherit