【问题标题】:Nashorn and script binding scopesNashorn 和脚本绑定范围
【发布时间】:2014-05-30 16:53:53
【问题描述】:

对 Nashorn 中的 ENGINE_SCOPE 和 GLOBAL_SCOPE 绑定有些困惑,尝试关注here 的讨论。

在阅读本文之前,我对范围的理解(至少在 rhino 中)是在 GLOBAL_SCOPE 中有一个共享的绑定,在 ENGINE_SCOPE 中为每个单独的引擎提供单独的绑定。然而,这个页面似乎在说每个单独的引擎都将基本的 javascript 构造存储在引擎 ENGINE_SCOPE 中存在的绑定中(混淆地称为“Nashorn 全局范围”)。这听起来像是让 GLOBAL_SCOPE 绑定实际上毫无用处(因为它们无法访问任何这些基本结构)。

我要做的是创建一个上下文,我可以将一些脚本注入其中,然后在这些脚本的上下文中反复评估不同的绑定。但是,如果我可以访问的唯一上下文是单个引擎 ENGINE_SCOPE(因为上面的任何内容都无法访问基本的 javascript 构造),那么似乎任何本地调用都必须添加到这些相同的绑定中。有谁知道如何在 Nashorn 中管理多个级别的绑定?

【问题讨论】:

    标签: nashorn


    【解决方案1】:

    如果在 ENGINE_SCOPE 中未找到变量,则会搜索 GLOBAL_SCOPE 绑定。 Nashorn 的全局对象(具有 JS Object、Number、RegExp、parseInt 等的对象)被包装为 Bindings - 这就是您的 ENGINE_SCOPE。例如。如果您将“foo”->“hello”映射条目放入 GLOBAL_SCOPE,这将在脚本中可见 - 如果 ENGINE_SCOPE 没有名为“foo”的映射条目。

    【讨论】:

    • 是的,来自wiki.openjdk.java.net/display/Nashorn/…,看起来是你写的。感谢您写下这篇文章,这是我能找到的为数不多的此类信息之一。很抱歉,我读了好几遍,仍然无法完全理解。
    • 其实,如果你熟悉这个,也许你知道答案:当我调用 scriptEngine.getContext() 时,我得到的是一个新实例还是同一个实例?如果相同,我如何获得新的(不是共享的)上下文? scriptContext.getBindings() 怎么样?新的绑定实例?旧绑定实例?如果有一个示例,尤其是多线程示例,将会非常有帮助 - 即多个资源加载一个共享脚本并使用各自的绑定运行它。很难找到有关其行为方式的清晰文档。
    • Steve,我正在努力解决同样的问题,即“几个资源加载一个共享脚本,每个资源都使用各自的绑定运行它”。你有没有找到关于这个话题的东西?另外,您可能对我发现的这个 stackoverflow.com/questions/27324802/… 错误感兴趣。
    • 我有第二个 Steve B.,我认为对围绕上下文的重用问题说“是”或“否”非常重要: 1. 如何在一个引擎中使用多个上下文而不污染它们执行 2. 编译后的代码是否可重用? 3. 引擎可以在多个线程上使用吗?有些人已经这样做了。根据它的属性,它不是。 Engines each need to warmup their code
    【解决方案2】:

    ENGINE_SCOPE 基本上是指放入绑定中的变量仅适用于该特定引擎,而GLOBAL_SCOPE 是指放入绑定中的变量可由同一工厂的所有引擎访问。

    是的,你是对的,如果在 ENGINE_SCOPE 中找不到任何变量,它自然会在 GLOBAL_SCOPE 中搜索。

    根据 JavaDoc

    static final int ENGINE_SCOPE
    EngineScope 属性在单个 ScriptEngine 的生命周期内可见,并且为每个引擎维护一组属性。

    static final int GLOBAL_SCOPE
    GlobalScope 属性对同一 ScriptEngineFactory 创建的所有引擎可见。

    我们可以在 Nashorn 中使用与此类似的脚本上下文来使用多个作用域

        context = new SimpleScriptContext(); // Script Context is an interface therefor you need to use an implementation of it
        context.setBindings(engine.createBindings(), SCOPE); // Set the bindings of the context, you can then use the context as an argument with the eval method of the script engine. Here engine is again an instance of javax.script.ScriptEngine
        Bindings bindings = context.getBindings(SCOPE); // Now use this for "putting" variables into the bindings SCOPE should either be ScriptContext.ENGINE_SCOPE or ScriptContext.GLOBAL_SCOPE
        bindings.put("x", "hello world");
        // Once done you must set the bindings
        context.setBindings(scope, SCOPE);
        // This code is just rough, I'm 100% sure there can always be further optimizations to this
        // Now finally evaluate your code
        engine.eval("Some pice of code..", context);   
        // Or you can use engine.setContext(YourContext) method in case you'll use your engine as an Invocable
        engine.setContext(context);
        engine.eval("Some piece of code");
        /* Do this because sometimes due to a bug you might not be able to call methods or functions from evaluated script
        Knowing about SrciptContext will help you a lot
        Note you can have multiple contexts and switch between them like I said
        Context parameter is also applicable for eval(Reader);
        */
    

    希望对你有帮助

    【讨论】:

    • 这不是真的:“GLOBAL_SCOPE 是指放入绑定的变量可以被同一工厂的所有引擎访问。”
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多