fgb fgb - 1 year ago 77
Java Question

Inconsistent output in Nashorn after accessing undefined value

I'm trying to create a console interface to a Java program using Nashorn. So I want some input to be evaluated against some default imports. The problem is when it accesses an undefined value. Ideally,

engine.eval
should throw a
ReferenceError
, or return
null
, but I'm getting inconsistent values later on:

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 }"));
}
}


The result on ideone and Windows Oracle JDK 1.8.0_101 is:

null
1
null


The last output is
null
, but adding
x == null
gives false.

I get this output if I add any spaces to the first string:

null
1
1


It seems that the last value is
null
if the first and last
engine.eval
parameters are exactly the same, including whitespace.

The value of
x
can go back between
null
and
1
so it looks like some kind of caching in the engine:

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 }"));
}
}


Gives:

null
1
null
1
2.0
null


Is there someway to get this to consistently give the
null, 1, 1
results?

fgb fgb
Answer Source

There is a class cache within the engine, which can be disabled by creating it with:

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

By forcing each expression to be recompiled, it seems to solve the issue. It looks like the same expression is compiled differently depending on which variables are in scope.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download