java - 评估脚本后读取更新的变量

标签 java jsr223 nashorn

我正在测试一些与 Rhino 一起工作的 JSR 223(脚本)代码,以了解它如何与 Nashorn 一起工作。一个不同之处在于对通过 engine.eval()Bindings 参数传入的变量的更新处理。在 Rhino 中,我可以使用此方法在评估脚本时传入动态变量绑定(bind),然后在执行脚本后读出这些变量的任何更新值。然而,在 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"),但与仅将绑定(bind)作为参数传递相比,这似乎有点困惑。

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

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

最佳答案

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

根据 the OpenJDK wikithis OpenJDK bug , Rhino 和 Nashorn 之间的这种行为差异是意料之中的。 Nashorn 并非旨在与 Rhino 100% 直接兼容。

关于java - 评估脚本后读取更新的变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24142979/

相关文章:

java - 更新 hibernate 对象时将数据类型 nvarchar 转换为十进制错误时出错

java - 在Java中如何在执行时注入(inject)代码?

javascript - 如何将 Javascript native 类型从 Java 传递给 Nashorn 对象?

java - 从 java servlet 访问环境变量

java - XML 中定义的 boolean 值。如何在 Java 中引用?

java - JRuby 类和 Java 脚本引擎意外结果

java - 实现 Nashorn ClassFilter 等价物

javascript - 将 Nashorn 迁移到 GraalVM

java - 从Java中的文本文件中读取数据作为数组

java - 从 JavaScript 实现 Java 接口(interface)失败并出现 TypeError