【问题标题】:Reading updated variables after evaluating a script在评估脚本后读取更新的变量
【发布时间】:2014-06-10 13:59:12
【问题描述】:

我正在测试一些适用于 Rhino 的 JSR 223(脚本)代码,以了解它如何适用于 Nashorn。一个不同的领域是处理通过Bindings 参数传递给engine.eval() 的变量的更新。在 Rhino 中,我可以在评估脚本时使用此方法传入动态变量绑定,然后在执行脚本后读取这些变量的任何更新值。然而,在 Nashorn 中,这不起作用 - Bindings 对象中的所有变量的值在执行脚本后仍然以其初始值存在。

用一个 TestNG 测试用例来说明:

@Test
public void shouldSupportReadingVariablesFromBindings() throws Exception {
    // Given
    ScriptEngine engine = new ScriptEngineManager().getEngineByName("javascript");
    Bindings vars = new SimpleBindings();
    vars.put("state", 1);

    // When
    engine.eval("state = 2", vars);
    Number result = (Number) vars.get("state");

    // Then
    assertEquals(result.intValue(), 2);

}

使用 Rhino(Mac OS X 10.9.3 上的 Apple JDK 1.6.0_65)测试通过。使用 Nashorn (Oracle JDK 1.8.0_b132) 它失败了。之后我尝试了各种不同的方法来读取变量 - 调用engine.get()engine.getBindings(ScriptContext.ENGINE_SCOPE).get()engine.getContext().getBindings(...).get() 等。结果总是null

如果我调用engine.put("state", 1),然后用engine.get("state") 读取它,我可以让它工作,但与仅将绑定作为参数传递相比,这似乎有点混乱。

阅读 JSR-223 规范,我找不到任何支持这种用法的措辞,所以它是特定于引擎的吗?还有其他方法可以在 Nashorn 中完成我想要的吗?

编辑:一种可行的方法是将每个变量包装在 AtomicReference 中,然后在 Javascript 中调用显式的 .set(..) 方法。丑陋,但可能可行。

【问题讨论】:

    标签: java jsr223 nashorn


    【解决方案1】:

    如果您传递使用ScriptEngine.createBindings 创建的绑定,Nashorn 会将更新后的值存储在绑定中。 (我测试过。)

    根据the OpenJDK wikithis OpenJDK bug,Rhino 和 Nashorn 之间的这种行为差异是可以预料的。 Nashorn 并非 100% 兼容 Rhino。

    【讨论】:

    • 谢谢,这是有用的信息。在我们的测试中,我们发现 Nashorn 比 Rhino 更需要内存,因此我们捆绑了自己的 Rhino 以获得跨 JDK 版本/供应商的一致行为。 Nashorn 在我们的特定用例(小脚本,主要是进行 REST 调用并处理结果)上的加速无论如何都可以忽略不计。
    猜你喜欢
    • 2018-04-29
    • 1970-01-01
    • 1970-01-01
    • 2010-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多