0

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

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

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

// 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尝试PolyglotLanguage为 optionName找到 a 时会发生这种情况js。事实证明,这是 IntelliJ 与从可运行的 .jar 运行之间的区别。IntelliJ 包含对 JavaScript 的支持PolyglotLanguage,而 .jar 不包含。这是我发现的

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

智能:

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()尝试将jsoptionName 与匹配时JavaScript PolyglotLanguage,会发生异常。

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

4

1 回答 1

0

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

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

#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
于 2021-10-12T14:53:16.553 回答