我正在尝试使用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
的值可以在null
和1
之间返回,因此它看起来像引擎中的某种缓存:
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
结果?
答案 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" });
通过强制重新编译每个表达式,它似乎解决了这个问题。看起来同一个表达式的编译方式不同,具体取决于范围内的变量。