Search code examples
javajava-8classcastexceptionnashorn

Why does Java 8's Nashorn engine in strict mode throw a java.lang.ClassCastException when calling apply() and passing the arguments object directly?


When I call eval (in strict mode) on a nashorn engine with the following script I get an exception:

var yfunc = function () {
  (null).apply(null, arguments);
};
yfunc();

I've truncated my personal situation heavily. The "(null)" on line 2 can be replaced with anything between parenthesis or a local variable, either way just something that shouldn't throw a compile error, and it will yield the same result.

The issue seems to be explicitly that "arguments" is passed directly as the second argument of calling a method called "apply". Any of the following changes will undo the thrown exception:

  1. Putting "arguments" in a variable first (but simply wrapping it in parenthesis doesn't work!)
  2. Calling something other than apply
  3. Passing "arguments" in a different argument slot when calling apply
  4. Calling print() (with or without passing any arguments) as a preceding line of code inside yfunc() (weird huh?)
  5. Defining more than 0 parameters for yfunc()
  6. Binding yfunc first and then calling the bound method
  7. Calling yfunc via Function.apply (not so much with Function.call!)

The Exception thrown is this:

Exception in thread "main" java.lang.ClassCastException: Cannot cast jdk.nashorn.internal.runtime.Undefined to jdk.nashorn.internal.runtime.ScriptFunction
at java.lang.invoke.MethodHandleImpl.newClassCastException(MethodHandleImpl.java:361)
at java.lang.invoke.MethodHandleImpl.castReference(MethodHandleImpl.java:356)
at jdk.nashorn.internal.scripts.Script$\^eval\_.:program(<eval>:4)
at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:637)
at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:494)
at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:393)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:449)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:406)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:402)
at jdk.nashorn.api.scripting.NashornScriptEngine.eval(NashornScriptEngine.java:155)
at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:264)

When I call this method with an owner, the exception thrown changes. Example code:

var yfunc = {
    method: function () {
          (null).apply(null, arguments);
    }
};
var x = yfunc.method();

Then the thrown exception looks like this:

Exception in thread "main" java.lang.ClassCastException: Cannot cast jdk.nashorn.internal.scripts.JO4 to jdk.nashorn.internal.runtime.ScriptFunction
at java.lang.invoke.MethodHandleImpl.newClassCastException(MethodHandleImpl.java:361)
at java.lang.invoke.MethodHandleImpl.castReference(MethodHandleImpl.java:356)
at jdk.nashorn.internal.scripts.Script$\^eval\_.:program(<eval>:5)
at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:637)
at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:494)
at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:393)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:449)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:406)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:402)
at jdk.nashorn.api.scripting.NashornScriptEngine.eval(NashornScriptEngine.java:155)
at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:264)

I've reproduced the issue so far on specifically these environments:

  • windows 7 64bit -> jdk 1.8.0_60 64bit
  • windows 8 64bit -> jdk 1.8.0_131 64bit

I can't seem to find anything on the internet about similar issues. Do I need to report this to Oracle/OpenJDK?

Minor update

Added items 6 and 7 to list of "following changes will undo the thrown exception".

Final update

Bug filed: JDK-8184720


Solution

  • Yes, it appears to be a bug. Please file a bug.