DEV Community

Cover image for JavaScript Meets Java: Nashorn Engine Explained
uttesh
uttesh

Posted on

JavaScript Meets Java: Nashorn Engine Explained

Image description

JS execution in JVM

The Nashorn engine in Java is a JavaScript engine introduced in Java 8. Which is suspected to have been deprecated by Java 11 and is now still available under OpenJDK Nashron.

It was a power feature that enabled the possibility of execution of Javascript code with JVM and made the result available for the Java code.

It's based on the ECMAScript Edition 5.1 standard and provides improved performance compared to earlier JavaScript engines in Java.
Here's a brief overview of the architecture of the Nashorn engine and how execution of external JavaScript (JS) files happens:

Architecture:

  • Nashorn is implemented as part of the Java Development Kit (JDK) and is included in the javax.script package.
  • It provides a way to execute JavaScript code within Java applications, allowing seamless integration of JavaScript and Java.
  • Nashorn internally converts JavaScript code to Java bytecode, which is then executed by the Java Virtual Machine (JVM).
  • It offers features like support for Java objects within JavaScript code, improved performance compared to earlier JavaScript engines in Java, and compatibility with existing Java tools and libraries.

Use case

When a UI-related feature, such as a TypeScript or JavaScript library, is developed and the result is needed as an API from a Java service. Instead of re-developing the JavaScript library feature in Java, we can use Nashorn to execute the library and obtain the results.

How to execute the JavaScript code sample code:

import javax.script.*;

public class NashornExample {
    public static void main(String[] args) throws Exception {
    // Create a new Nashorn script engine
    ScriptEngineManager manager = new ScriptEngineManager();
    ScriptEngine engine = manager.getEngineByName("nashorn");
    // Load and execute the JavaScript code
    String script = "function add(a, b) { return a + b; } 
                       add(3, 4);";
        Object result = engine.eval(script);
        // Output the result
        System.out.println("Result: " + result);
    }
}
Enter fullscreen mode Exit fullscreen mode

We can use the existing lib JS or write the JavaScript code in a separate JS file and execute that through the Engine.

To execute an external JavaScript file with Nashorn, you typically load the file using the ScriptEngine and then evaluate its contents.

Image description

import javax.script.*;

public class NashornExample {
    public static void main(String[] args) throws Exception {
        // Create a new Nashorn script engine
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("nashorn");

        // Load and execute an external JavaScript file
        engine.eval(new java.io.FileReader("path/to/your/script.js"));
    }
}

Enter fullscreen mode Exit fullscreen mode

In Nashorn, the eval function works similarly to other JavaScript engines, but with some differences due to its implementation in Java. Nashorn is designed to execute JavaScript code within the Java Virtual Machine (JVM), providing seamless integration between Java and JavaScript.

Here's a brief overview of what happens internally when you use the eval function in Nashorn:

Parsing and Compilation: When you call eval with a string argument containing JavaScript code, Nashorn parses the string into an abstract syntax tree (AST), just like other JavaScript engines. However, Nashorn also performs Just-In-Time (JIT) compilation of the parsed code into Java bytecode. This bytecode can then be executed directly by the JVM.

Execution: Nashorn executes the compiled bytecode within the JVM, leveraging the Java runtime environment for memory management, threading, and other runtime services. This allows Nashorn to achieve better performance compared to pure interpretation in some cases.

Access to Java APIs: One of the key features of Nashorn is its seamless integration with Java. JavaScript code executed via eval in Nashorn has access to Java APIs and can interact with Java objects and classes directly. This makes it easy to use JavaScript to script Java applications or extend Java functionality.

Image description

Overall, the eval function in Nashorn allows you to dynamically execute JavaScript code within the JVM, with access to Java APIs and services. However, it's important to use eval judiciously, considering security implications and potential performance overhead.

Nashorn Engine Modules:

  1. factory
  2. nashornContext
  3. global
  4. context
    • writer
    • errorWriter
    • reader
    • engineScope
      • lib
      • atob
      • btoa
      • clearImmediate
      • setImmediate
      • queueMicrotask
      • self
      • structureClone

In the context of Nashorn, lib typically refers to the built-in libraries or modules that are available for use within the Nashorn JavaScript engine. These libraries provide additional functionality and utilities that developers can leverage when writing JavaScript code to run on Nashorn.

The built-in libraries in Nashorn may include:

1. Java Integration:
Nashorn provides comprehensive support for integrating JavaScript with Java. This includes access to Java classes, methods, and objects directly from JavaScript code. With Nashorn, you can instantiate Java objects, call Java methods, and interact with Java APIs seamlessly from within your JavaScript code.

2. Standard ECMAScript Libraries:
Nashorn implements the ECMAScript standard, which defines the core features and functionalities of the JavaScript language. This includes built-in objects such as Array, Math, Date, and String, as well as standard global functions like parseInt, parseFloat, and isNaN.

3. Additional Nashorn-specific Libraries:
Nashorn may also include additional libraries or modules that are specific to its implementation. These libraries may provide utilities for interacting with the Nashorn runtime environment, accessing system resources, or performing common tasks within JavaScript applications running on Nashorn.

Overall, the lib inside Nashorn refers to the collection of built-in libraries and modules that are available for use within the Nashorn JavaScript engine. These libraries enhance the capabilities of Nashorn and enable developers to build powerful and feature-rich applications using JavaScript on the Java platform.

When using external libraries or files containing additional functions, Nashorn's eval parses all the functions exported to a lib.

To execute any function inside the lib, we must create a simple reference function that calls the functions in the lib.{function}.

I hope this blog helps in finding out about the JS execution in JVM.

The latest available engine could be GraalVM, GraalVM can step in as a replacement for JavaScript code previously executed on the Nashorn engine and J2V8 of eclipse

GraalVM: https://docs.oracle.com/en/graalvm/enterprise/20/docs/reference-manual/js/NashornMigrationGuide/#migration-guide-from-nashorn-to-graalvm-javascript

Top comments (0)