Java 8 Nashorn problem

Written by  on October 7, 2014 

I got a __noSuchProperty__ error when trying to use my old JavaScripts with Java 8. Despite the claims on this site: https://wiki.openjdk.java.net/display/Nashorn/Rhino+Migration+Guide which may change by the time you read this; so I’ll excerpt here:

JavaImporter and with

Nashorn supports JavaImporter constructor of Rhino. It is possible to locally import multiple java packages and use it within a ‘with’ statement.

It seems like there is some problem with the JavaImporter… or there’s some problem with the way I’m [ab]using it, of course. In any case, this page helped me locate the problem. I simply changed from using the Java StrictMath package to using the JavaSript Math package:

--- test.js	2014-10-07 10:34:15.771959410 -0700
+++ testnew.js	2014-10-07 10:34:20.739826080 -0700
-  tempy = StrictMath.exp(-constant*ind);
+  tempy = Math.exp(-constant*ind);

This just kicks the can down the street, of course. I may or may not have to solve the problem for real at some point. But this is fine for now. Perhaps when OpenJDK 8 is released, it’ll be easier to debug? Below is the rest of the story.

Execution:

gepr@yog:~/lang/java/js-script-engine$ java -cp . Eval
test eval(0.0) = 1.0 : test eval(0.0) = 1.0
test eval(10.0) = 4.539992976248485E-5 : test eval(10.0) = 0.006737946999085467
test eval(20.0) = 2.061153622438558E-9 : test eval(20.0) = 4.539992976248485E-5
test eval(30.0) = 9.357622968840175E-14 : test eval(30.0) = 3.059023205018258E-7
test eval(40.0) = 4.248354255291589E-18 : test eval(40.0) = 2.061153622438558E-9
gepr@yog:~/lang/java/js-script-engine$ sudo update-alternatives --config java
There are 4 choices for the alternative java (providing /usr/bin/java).

  Selection    Path                                            Priority   Status
------------------------------------------------------------
* 0            /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java   1071      auto mode
  1            /usr/bin/gij-4.8                                 1048      manual mode
  2            /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java   1071      manual mode
  3            /usr/lib/jvm/jdk-7-oracle-x64/jre/bin/java       317       manual mode
  4            /usr/lib/jvm/jdk-8-oracle-x64/jre/bin/java       318       manual mode

Press enter to keep the current choice[*], or type selection number: 4
update-alternatives: using /usr/lib/jvm/jdk-8-oracle-x64/jre/bin/java to provide /usr/bin/java (java) in manual mode
gepr@yog:~/lang/java/js-script-engine$ java -cp . Eval
test eval(0.0) = 1.0 : test eval(0.0) = 1.0
test eval(10.0) = 4.539992976248485E-5 : test eval(10.0) = 0.006737946999085467
test eval(20.0) = 2.061153622438558E-9 : test eval(20.0) = 4.539992976248485E-5
test eval(30.0) = 9.357622968840175E-14 : test eval(30.0) = 3.059023205018258E-7
Exception in thread "main" java.lang.AssertionError: __noSuchProperty__ placeholder called
	at jdk.nashorn.internal.objects.NativeJavaImporter.__noSuchProperty__(NativeJavaImporter.java:105)
	at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:557)
	at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:209)
	at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:378)
	at jdk.nashorn.internal.runtime.ScriptObject.invokeNoSuchProperty(ScriptObject.java:2113)
	at jdk.nashorn.internal.runtime.ScriptObject.megamorphicGet(ScriptObject.java:1805)
	at jdk.nashorn.internal.scripts.Script$\^eval\_.runScript(:5)
	at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:535)
	at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:209)
	at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:378)
	at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:568)
	at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:525)
	at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:521)
	at jdk.nashorn.api.scripting.NashornScriptEngine.eval(NashornScriptEngine.java:192)
	at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:233)
	at Eval.eval(Eval.java:31)
	at Eval.main(Eval.java:52)
gepr@yog:~/lang/java/js-script-engine$ 

Eval.java:

import java.io.FileNotFoundException;
import java.io.IOException;
import javax.script.ScriptException;

public class Eval {
  final static javax.script.ScriptEngineManager manager = new javax.script.ScriptEngineManager();
  final static javax.script.ScriptEngine engine = manager.getEngineByExtension("js");
  javax.script.ScriptContext context = new javax.script.SimpleScriptContext();
  public javax.script.Bindings scope = null;

  String script = null;

  public Eval(String fileName) {
    context.setBindings(engine.createBindings(), javax.script.ScriptContext.ENGINE_SCOPE);
    scope = context.getBindings(javax.script.ScriptContext.ENGINE_SCOPE);

    script = convertStreamToString(
             getClass().getClassLoader().getResourceAsStream(fileName));
  }

  public static String convertStreamToString(java.io.InputStream is) {
    java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
    return s.hasNext() ? s.next() : "";
  }

  public double eval(double t) {
    double retVal = Double.NaN;
    Object result = null;
    scope.put("ind", t);
    try {
      result = engine.eval(script,scope);
    } catch (ScriptException e) {
      System.err.println(e.getMessage());
      e.printStackTrace();
      System.exit(-1);
    }
    if (result instanceof Double)
      retVal = (Double)result;
    else
      retVal = ((Integer)result).doubleValue();
    return retVal;
  }

  public static void main(String args[]) {
    Eval se1 = null;
    Eval se2 = null;
    se1 = new Eval("test.js");
    se2 = new Eval("test.js");
    se1.scope.put("constant", 1.00);
    se2.scope.put("constant", 0.50);
    for (double t=0.0; t<50.0; t += 10.0) {
      System.out.print("test eval("+t+") = "+ se1.eval(t)+" : ");
      System.out.println("test eval("+t+") = "+ se2.eval(t));
    }
  }
}

test.js:

var math = new JavaImporter(java.lang.StrictMath);
var constant;
var ind;
with (math) {
  tempy = StrictMath.exp(-constant*ind);
}

Category : Uncategorized

Comments

2 Responses

  1. gepr says:

    Thanks to @sundararajan_a and @wickund for pointing out that this has been fixed in the pre-release of Java 8u40:

    gepr@yog:~/lang/java/js-script-engine$ java -version
    java version "1.8.0_40-ea"
    Java(TM) SE Runtime Environment (build 1.8.0_40-ea-b07)
    Java HotSpot(TM) 64-Bit Server VM (build 25.40-b11, mixed mode)
    gepr@yog:~/lang/java/js-script-engine$ java -cp . Eval
    test eval(0.0) = 1.0 : test eval(0.0) = 1.0
    test eval(10.0) = 4.539992976248485E-5 : test eval(10.0) = 0.006737946999085467
    test eval(20.0) = 2.061153622438558E-9 : test eval(20.0) = 4.539992976248485E-5
    test eval(30.0) = 9.357622968840175E-14 : test eval(30.0) = 3.059023205018258E-7
    test eval(40.0) = 4.248354255291589E-18 : test eval(40.0) = 2.061153622438558E-9
    
  2. gepr says:

    Oops. I spoke too soon. It’s not fixed:

    test eval(0.0) = 1.0 : test eval(0.0) = 1.0
    test eval(10.0) = 4.539992976248485E-5 : test eval(10.0) = 0.006737946999085467
    test eval(20.0) = 2.061153622438558E-9 : test eval(20.0) = 4.539992976248485E-5
    test eval(30.0) = 9.357622968840175E-14 : test eval(30.0) = 3.059023205018258E-7
    test eval(40.0) = 4.248354255291589E-18 : test eval(40.0) = 2.061153622438558E-9
    test eval(50.0) = 1.9287498479639178E-22 : test eval(50.0) = 1.3887943864964021E-11
    test eval(60.0) = 8.75651076269652E-27 : test eval(60.0) = 9.357622968840175E-14
    test eval(70.0) = 3.975449735908647E-31 : test eval(70.0) = 6.305116760146989E-16
    test eval(80.0) = 1.804851387845415E-35 : test eval(80.0) = 4.248354255291589E-18
    test eval(90.0) = 8.194012623990515E-40 : Exception in thread "main" java.lang.AssertionError: __noSuchProperty__ placeholder called
    	at jdk.nashorn.internal.objects.NativeJavaImporter.__noSuchProperty__(NativeJavaImporter.java:108)
    	at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:654)
    	at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:226)
    	at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:381)
    	at jdk.nashorn.internal.runtime.ScriptObject.invokeNoSuchProperty(ScriptObject.java:2361)
    	at jdk.nashorn.internal.runtime.ScriptObject.megamorphicGet(ScriptObject.java:2029)
    	at jdk.nashorn.internal.scripts.Script$Recompilation$3$\^eval\_.:program(:5)
    	at java.lang.invoke.LambdaForm.interpret_L(LambdaForm.java:664)
    	at java.lang.invoke.LambdaForm.interpret_L(LambdaForm.java:664)
    	at java.lang.invoke.LambdaForm.interpret_L(LambdaForm.java:664)
    	at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:625)
    	at java.lang.invoke.LambdaForm.interpret_L(LambdaForm.java:664)
    	at java.lang.invoke.LambdaForm.interpret_L(LambdaForm.java:664)
    	at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:632)
    	at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:226)
    	at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:381)
    	at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:459)
    	at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:423)
    	at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:419)
    	at jdk.nashorn.api.scripting.NashornScriptEngine.eval(NashornScriptEngine.java:152)
    	at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:233)
    	at Eval.eval(Eval.java:31)
    	at Eval.main(Eval.java:53)
    

Leave a Reply