访问未定义值后,Nashorn中的输出不一致

时间:2016-08-19 19:54:01

标签: java nashorn

我正在尝试使用Nashorn为Java程序创建一个控制台界面。所以我希望根据一些默认导入来评估一些输入。问题是它访问未定义的值。理想情况下,engine.eval应该抛出ReferenceError,或者返回null,但我稍后会得到不一致的值:

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

public class Main {
    public static void main(String[] args) throws Exception {
        ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
        System.out.println(engine.eval("with(JavaImporter(java.util)) { x }"));
        System.out.println(engine.eval("with(JavaImporter(java.util)) { x = 1 }"));
        System.out.println(engine.eval("with(JavaImporter(java.util)) { x }"));
    }
}

ideone和Windows Oracle JDK 1.8.0_101上的结果是:

null
1
null

最后一项输出为null,但添加x == null会导致错误。

如果我在第一个字符串中添加任何空格,我会得到此输出:

null
1
1

如果第一个和最后一个null参数完全相同,包括空格,那么最后一个值似乎是engine.eval

x的值可以在null1之间返回,因此它看起来像引擎中的某种缓存:

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

public class Main {
    public static void main(String[] args) throws Exception {
        ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
        System.out.println(engine.eval("with(JavaImporter(java.util)) { x }"));
        System.out.println(engine.eval("with(JavaImporter(java.util)) { x = 1 }"));
        System.out.println(engine.eval("with(JavaImporter(java.util)) { x }"));
        System.out.println(engine.eval("with(JavaImporter(java.util)) { x  }"));
        System.out.println(engine.eval("with(JavaImporter(java.util)) { x + x }"));
        System.out.println(engine.eval("with(JavaImporter(java.util)) { x }"));
    }
}

给出:

null
1
null
1
2.0
null

是否有人能够始终如一地提供null, 1, 1结果?

2 个答案:

答案 0 :(得分:0)

强制引擎确认变量的声明。

只需在第一个脚本中使用var x

System.out.println(engine.eval("with(JavaImporter(java.util)) { var x }")); System.out.println(engine.eval("with(JavaImporter(java.util)) { x = 1 }")); System.out.println(engine.eval("with(JavaImporter(java.util)) { x }"));

答案 1 :(得分:0)

引擎中有一个类缓存,可以通过以下方式禁用它:

NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
ScriptEngine engine = factory.getScriptEngine(new String[] { "--class-cache-size = 0" });

通过强制重新编译每个表达式,它似乎解决了这个问题。看起来同一个表达式的编译方式不同,具体取决于范围内的变量。