Back

TechnologyDec 05, 2013

Java 8 Part 2 – Nashorn

Brian Davis

In part one of the Java 8 series we introduced functional interfaces, default methods, lambda expressions, and streams. Here in part two we will take a look at one of the biggest new additions: Nashorn, Oracle’s new, full 100% ECMA262-compliant JavaScript engine, implemented entirely in Java. Its core functionality provides the ability to interweave both Java and JavaScript, but in a broader sense, it can be most easily understood as Oracle’s latest effort to open up the JVM to languages other than Java and attract more developers.

We all know how well-established Java is, but as dynamic languages continue to grow in popularity, Java’s weaknesses are being underscored—namely its formal, rigid typing which leads to verbose code and slow development. By implementing a JavaScript engine in Java, Oracle is providing programmers access to all of the benefits of Java (extensive libraries, code optimization, vast support networks, etc.) for use in a flexible, dynamically-typed language that many programmers are already familiar with.

A Java implementation of JavaScript is nothing new. Rhino, developed by Netscape in 1997 and subsequently taken over by Mozilla, shipped with Java SE 6, and offered many of the same features as Nashorn, but was slow compared to other JavaScript engines. Its performance improved with the release of Java SE 7 by partially making use of the invokedynamic instruction, but it still paled in comparison to Google’s V8. Nashorn, by being built from scratch and making full use of invokedynamic, is essentially what Rhino was supposed to be. Early speed tests suggest that it still can’t match the performance of V8, but at roughly 3-5 times faster than Rhino, it’s at least a viable competitor at this point.

Before going into the various opportunities that Nashorn opens up, it’s easiest to first demonstrate how it allows you to interweave JavaScript and Java.

JavaScript in Java

The Java Scripting API can be used to execute JavaScript from within a Java class. A simple Hello, World program, for example, can be written as:

  1. import javax.script.*;

  2. ScriptEngineManager m = new ScriptEngineManager();

  3. ScriptEngine nashorn = m.getEngineByName("nashorn");

  4. try {

  5.                   nashorn.eval("print('Hello, world')");

  6. } catch (ScriptException e) {

  7. }

While this is a rather trivial use case, you can easily feed a full-blown .js file into the .eval() method for more serious uses by modifying line 5 as follows:

  1. nashorn.eval(new java.io.FileReader(“TestScript.js”));

With this functionality developers can, for example, call JavaScript template engines from within their Java code or use the same validator code on both the client and server side. It also opens up some interesting possibilities for multithreading.

Java in JavaScript

Going the other way, Nashorn comes with a global, predefined ‘Java’ object with several functions for working with Java classes directly within JavaScript. For example, consider a simple Java class that gets a user name from its constructor, and has a method that returns a greeting:

  1. package com.credera.example;

  2. public class HelloUser {

  3.                   private String name;

  4.                   public HelloUser(String name) {

  5.                                     this.name = name;

  6.                   }

  7.                   public String getMessage() {

  8.                                     return "Hello, " + this.name;

  9.                   }

  10. }

The Java object can be used to import the HelloUser class into a JavaScript by

  1. var HelloUser = Java.type("com.credera.example.HelloUser");

and we can then create a new HelloUser object and invoke the .getMessage() method by

  1. var helloUser = new HelloUser("John");

  2. print(helloUser.getMessage())

The code above can be run from the command line using the new jjs tool included with JDK 8 as follows:

  1. jjs -cp /com/credera/example/HelloUser TestNashorn.js

jjs (short for Java/JavaScript) comes with its own suite of interesting functionality as well. Simply typing jjs will open up an interactive command line interface, allowing you to execute and test individual snippets of code. Additionally, jjs allows JavaScript scripts to accept shebang notation, thus making JavaScript a suitable language for coding and executing shell scripts.

As these two examples suggest, most of the benefits of Nashorn lie on the server side. In fact, the only real use for it on the client side that I could find is with javaFX applications, which can be developed much faster in JavaScript than in Java (a nice example of this can be found here in the Nashorn documentation)).

Looking to the future, though, Oracle appears to have big plans for Nashorn, and more generally, scripting on the JVM. The invokedynamic protocol, for example, is more flexible than I may have let on here. Dynalink is an invokedynamic-based library developed for Nashorn that allows it to link between various objects. As Jim Laskey, the multi-language lead at Oracle, discussed in his EclipseCon keynote, in a statement like “var x = object.property;”, the object’s type is not known at compile time, and Dynalink allows the JVM to dynamically determine the type at runtime. In time, the Dynalink library can grow to handle objects in other languages like Ruby, in addition to just Java and JavaScript. Further, Oracle is in the process of developing node.jar, a java implementation of node.js to also run on the JVM via Nashorn.

So, it’s clear that Nashorn will open up several exciting possibilities, but what remains unclear is just how much of an impact it will have. Node.js, for example, can already accomplish most of the server-side benefits discussed here, and simply saying that Nashorn lets developers run JavaScript on the JVM is not exactly a huge selling point since other engines still offer better performance. Is access to Java libraries and the JVM enough to attract developers? The Nashorn team has demonstrated some pretty interesting applications at the Nashorn blog, but we’ll have to wait and see how (and if) developers begin to adopt this new engine to determine the ultimate impact it will have.

Stay tuned for parts three and four of the Java 8 series to learn about the improvements and bug fixes on existing libraries being shipped with JDK 8.

This post is part two of a series covering Java 8:

Java 8 Part 1 – Lamdas, Streams, and Functional Interfaces

– Java 8 Part 2 – Nashorn

Java 8 Part 3 – HashMap and java.time

– Java 8 Part 4 – Concurrency, TLS SNI, and PermGen

Have a Question?

Please complete the Captcha