Skip to content

Instantly share code, notes, and snippets.

@bric3
Last active January 20, 2022 17:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bric3/59906de4fb161ac71d5d5aff15c51e96 to your computer and use it in GitHub Desktop.
Save bric3/59906de4fb161ac71d5d5aff15c51e96 to your computer and use it in GitHub Desktop.
Upgrade to / use GraalJS (instead of nashorn)

Nashorn is deprecated since Java 11, it has been removed in Java 15. In order to run javascript, it is necessary to upgrade the script engine. The most common alternative as of now is GraalVM JS engine.

build.gralde
  dependencies {
+     implementation("org.graalvm.js:js:22.0.0")
+     implementation("org.graalvm.js:js-scriptengine:22.0.0")
  }

Then adapt the code. Either replace the engine name new ScriptEngineManager().getEngineByName("graal.js") or use the GraalJS API.

Replace by Graal JS API
-     ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
+     ScriptEngine engine = new GraalJSEngineFactory().getScriptEngine();

  try (Reader reader = Files.newBufferedReader(jsPath)) {) {
      engine.eval("var window={}, navigator=null;");
      engine.eval(reader);
  } catch (IOException | ScriptException ex) {
      ex.printStackTrace();
  }

By default the Graal Js do not have the Java extensions that allows to refer to Java types. This can be changed with a system property before starting the engine. Read the documentation on nashorn compatibility.

System.setProperty("polyglot.js.nashorn-compat", "true");

There is also the interpeted mode warning to take into account.

[To redirect Truffle log output to a file use one of the following options:
* '--log.file=<path>' if the option is passed using a guest language launcher.
* '-Dpolyglot.log.file=<path>' if the option is passed using the host Java launcher.
* Configure logging using the polyglot embedding API.]
[engine] WARNING: The polyglot context is using an implementation that does not support runtime compilation.
The guest application code will therefore be executed in interpreted mode only.
Execution only in interpreted mode will strongly impact the guest application performance.
For more information on using GraalVM see https://www.graalvm.org/java/quickstart/.
To disable this warning the '--engine.WarnInterpreterOnly=false' option or use the '-Dpolyglot.engine.WarnInterpreterOnly=false' system property.

The solution is to enable the JVM Compiler Interface, as explained here.

There’s the org.graalvm.plugin.compiler (0.1.0-alpha2) gradle plugin that does this job. The only complaint is that it is still in alpha and not opensource

  plugins {
      id("java")
+     id("org.graalvm.plugin.compiler") version "0.1.0-alpha2"
  }

+ graal {
+     version = "22.0.0"
+ }

This plugin will add a prepareCompiler task that will download three artefacts according to the given version, in a specific folder (build/graalCompiler):

  • compiler-22.0.0.jar

  • graal-sdk-22.0.0.jar

  • truffle-api.jar-22.0.0.jar

Then will patch the JavaExec tasks and adds the following VM parameters

  • -XX:+UnlockExperimentalVMOptions

  • -XX:+EnableJVMCI

  • --module-path=/Users/brice.dutheil/go/src/github.com/DataDog/opensource/fireplace/build/graalCompiler

  • --upgrade-module-path=/Users/brice.dutheil/go/src/github.com/DataDog/opensource/fireplace/build/graalCompiler

Then you have the latest Graal compiler running on the stock JDK.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment