The Java platform and runtime is an intentional home to many languages beyond the Java language itself. OpenJDK’s Da Vinci Machine helps coordinate work amongst language developers and tool designers and has helped different languages by introducing the Invoke Dynamic instruction in Java 7 (2011), which resulted in two major benefits: speeding up execution of dynamic code, and providing the groundwork for Java 8’s lambda executions. Many of these improvements are discussed at the JVM Language Summit, where language and tool designers get together to discuss experiences and issues related to building these complex components.
Scripts do not need to be compiled.
The ability to remotely debug applications using an IDE like NetBeans, Eclipse, or IntelliJ (instructions on the Nashorn blog).
Automatic integration with Java monitoring tools, such as performance, health, and SIEM.
In the remainder of this blog post, I will explain how to use Nashorn and the benefit from those features.
Nashorn execution environment
The Nashorn scripting engine is included in all versions of Java SE 8, both the JDK and the JRE. Unlike Java code, scripts written in nashorn are interpreted and do not need to be compiled before execution.
Developers and users can access it in two ways:
This mechanism can also be used in shell scripts by specifying a shebang like #!/usr/bin/jjs
Developers can use the API and obtain a ScriptEngine through:ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
When using a ScriptEngine, please understand that they execute code. Avoid running untrusted scripts or passing in untrusted/unvalidated inputs. During compilation, consider isolating access to the ScriptEngine and using Type Annotations to only allow @Untainted String arguments.
The Nashorn script engine allows developers of all experience levels the ability to write and run code that takes advantage of both languages. The specific dialect is ECMAScript 5.1 as identified by the User Guide and its standards definition through ECMA international.
In addition to the example below, Benjamin Winterberg has a very well written Java 8 Nashorn Tutorial that provides a large number of code samples in both languages.
A basic Hello World application written to run on Nashorn would look like this:
The first line is a standard script indication, so that Linux or Unix systems can run the script through Nashorn. On Windows where scripts are not as common, you would run the script like: jjs helloWorld.js.
In order to receive program arguments your jjs invocation needs to use the -scripting flag and a double-dash to separate which arguments are for jjs and which are for the script itself:jjs -scripting print.js -- "This will print"
var whatYouSaid = $ARG.length==0 ? "You did not say anything" : $ARG
Interoperability with Java libraries (including 3rd party dependencies)
Another goal of Nashorn was to allow for quick scriptable prototypes, allowing access into Java types and any libraries. Resources operate in the context of the script (either in-line with the script or as separate threads) so if you open network sockets and your script terminates, those sockets will be released and available for your next run.
Your code can access Java types the same as regular Java classes. The “import statements” are written somewhat differently to accommodate for language. There is a choice of two styles:
For standard classes, just name the class: var ServerSocket = java.net.ServerSocket
For arrays or other items, use Java.type: var ByteArray = Java.type("byte")You could technically do this for all.
The same technique will allow your script to use Java types from any library or 3rd party component and quickly prototype items.
Building a user interface
Nashorn has a -fx flag to make the user interface components available. With the example script below, just specify: jjs -fx -scripting fx.js -- "My title"
var Button = javafx.scene.control.Button;
var StackPane = javafx.scene.layout.StackPane;
var Scene = javafx.scene.Scene;
$STAGE.title = $ARG.length>0 ? $ARG : "You didn't provide a title";
var button = new Button();
button.text = "Say 'Hello World'";
button.onAction = myFunctionForButtonClicking;
var root = new StackPane();
$STAGE.scene = new Scene(root, 300, 250);
var text = "Click Counter: " + clickCounter;
For a more advanced post on using Nashorn to build a high-performing UI, see JavaFX with Nashorn Canvas example.
Interoperable with frameworks like Node, Backbone, or Facebook React
A number of projects are also running Node applications on Nashorn through Project Avatar and the supported modules.
In addition to the previously mentioned Nashorn tutorial, Benjamin has also written a post about Using Backbone.js with Nashorn.
To show the multi-language power of the Java Runtime, there is another interesting example that unites Facebook React and Clojure on JDK 8’s Nashorn.
Software Architects and System Administrators can take advantage of one runtime and leverage any work that they have done to tune, monitor, and certify their systems.
Additional information is available within:
The Nashorn Users’ Guide
The Nashorn team’s primary blog or a very helpful collection of Nashorn links.