将 Nashorn 迁移到 GraalVM 以缓存和执行脚本

Migrating Nashorn to GraalVM to cache and execute scripts

所以我有一个 java 应用程序,它使用 NashornScriptEngine 创建一个 CompiledScript,然后我可以在其中创建一个 Invocable。编译的脚本是从一个文件输入编译的,这是我正在尝试 运行 的 js。然后我将这个 Invocable 缓存在一个映射中以便稍后执行。使用它就像

一样简单
import javax.script.Invocable;

public void handleEvent(Event event, Processor processor){
    try {
        Invocable script = cache.get(event);
        if(script != null) {
            script.invokeFunction("run", data);
        } else {
            throw new UnsupportedOperationException(event.name());
        }
    } catch (Exception exception) ...
}

但是,由于 Nashorn 已被弃用,我正在尝试切换到 GraalVM,同时实现相同的目的。我看到一些 GitHub 页面讨论了这个,但老实说它对我没有帮助。这是我正在看的一些。

https://github.com/graalvm/graaljs/blob/master/docs/user/ScriptEngine.md https://github.com/graalvm/graaljs/issues/78

我发现这是最有用的,但是它不允许我在入口点调用,就像我上面的代码一样,我也不能创建一个可调用的缓存并在以后调用。

    public void compile(File file){
        try {
            Source source = Source.newBuilder("js", file).build();
            Engine engine = Engine.create();

            Context context = Context.newBuilder("js").engine(engine).option("js.nashorn-compat", "true").build();
            context.eval(source);
            context.close();
        } catch (Exception exception){
            exceptionCaught(exception);
        }
    }

关于如何使用 GraalVM 将文件 (js) 编译为可调用文件的任何提示?谢谢!

context.eval() 将 return 类型为 org.graalvm.polyglot.Value 的值。当 source return 为 function 时,此值将用 true 回答 canExecute(),您可以重复 value.execute(args...)。查看 API 的值:https://www.graalvm.org/truffle/javadoc/org/graalvm/polyglot/Value.html

我看到您正在设置 nashorn-compat 选项。请理解这是一个向后兼容的选项,您最好不要使用。在许多情况下,如果没有该选项,您的代码将 运行 完美。请检查 Migration guide 以了解在 Nashorn 模式下可用的 GraalVM JavaScript 确实不支持的情况。