Skip to content
Advertisement

Standalone Nashorn with Java 11 throws java.lang.StackOverflowError upon eval

I came across an issue with Nashorn, when evaluating a large expression, it works fine in Java 8 , but throws a java.lang.StackOverflowError in Java 11.

JavaScript

I came across this question, and in an attempt to fix this issue, as suggested in this comment, I’m trying to use the Standalone Nashorn with Java 11, by using org.openjdk.nashorn.api.scripting.NashornScriptEngineFactory in my code (See this page for info on “why do we need to do that”).

I’m having a simple Maven project, where I have added the following to my pom. For simplicity, I’ve included only the following important parts:

  • Nashorn dependency
  • Maven Compiler Plugin
JavaScript

(Apart from these, I’m using maven-dependency-plugin and maven-jar-plugin to bundle this into an executable Jar).

The following is my Java code: Main.java

JavaScript

With Java version java version “11.0.9” 2020-10-20 LTS, I’m compiling a jar called maven-project-1.0-SNAPSHOT.jar via doing mvn clean install.

When running the main class of the Jar as follows:

JavaScript

Based on this information, the standalone version of Nashorn will be loaded with Java 11 since I have used org.openjdk.nashorn.api.scripting.NashornScriptEngineFactory, and therefore, I’m not expecting a java.lang.StackOverflowError with Java 11.

But my output produces a StackOverflowError:

JavaScript

Update: When compiling this with Java 17 and testing, I did not get a StackOverflowError. As pointed out by @Thorbjørn Ravn Andersen in the comments, the reason to check this was, to rule out the possibility of the in-built Nashorn being picked in Java 11, instead of the standalone one. (Since Java 17 doesn’t have the inbuilt Nashorn, it would pick only the standalone one).

Based on this, I can also think of an addition to this question:

how can we make sure that the standalone Nashorn is picked up in Java 11?

I tried executing the jar as follows (referred to this answer of this related question), but the StackOverflowError is still being thrown. (The /path/to/my/maven-project/target/libs/ directory contains jars such as nashorn-core-15.3.jar, asm-7.3.1.jar, asm-commons-7.3.1.jar …)

JavaScript

(Instead of passing arguments/flags like this, a preferrable way would be to add these as a configuration or so in the pom – and handle it “neater”).


FYI, The following code works fine with Java 8, but throws the same StackOverflowError in Java 11, which is why I had to use org.openjdk.nashorn.api.scripting.NashornScriptEngineFactory instead of javax.script.ScriptEngineManager.

JavaScript

Am I missing anything here? Thanks in advance for any solutions.

Advertisement

Answer

How long is the actual source code expression that in the JavaScript code that causes this?

You are not getting the exception in Java 8 because Nashorn in Java 8 didn’t have some of the more advanced static type inference capabilities which allow it to generate more optimal code when it can prove some variables will always be ints or doubles and never objects.

This static type inference was added in a later Nashorn version, one released with Java 9. The stack overflow happens in its code as it needs to recursively walk the expression tree. If you have an extremely long expression, this might happen. I’d suggest you break very long expressions into smaller ones, either isolating them into local functions or assigning them to local variables. Local functions are better as then you can keep short-circuited evaluation, e.g. if you had

JavaScript

you can instead do

JavaScript

This example just illustrates the technique, Nashorn should be good to evaluate very long expressions before running into a stack overflow.


Alternatively, run your JVM with explicit -Xss setting to give threads more stack memory.

User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement