|
1 | | -Nashorn |
| 1 | +Nashorn: Run JavaScript on the JVM |
2 | 2 | ----- |
| 3 | + |
| 4 | + |
| 5 | + |
| 6 | +Nashorn is a high-performance JavaScript runtime written in Java for the JVM. It allows developers to embed JavaScript code inside their Java applications and even use Java classes and methods from their JavaScript code. You can think it as an alternative to Google's V8 JavaScript engine. It is a successor to Rhino JavaScript runtime which came bundled with earlier JDK versions. Nashorn is written from scratch using new language features like JSR 292(Supporting Dynamically Typed Languages) and `invokedynamic`. |
| 7 | + |
| 8 | +From the Nashorn documentation: |
| 9 | +> Nashorn uses invokedynamic to implement all of its invocations. If an invocation has a Java object receiver, Nashorn attempts to bind the call to an appropriate Java method instead of a JavaScript function. Nashorn has full discretion about how it resolves methods. As an example, if it can't find a field in the receiver, it looks for an equivalent Java Bean method. The result is completely transparent for calls from JavaScript to Java. |
| 10 | +
|
| 11 | +Currently, Nashorn supports [ECMAScript 5.1 specification](http://www.ecma-international.org/ecma-262/5.1/) and work is in progress to support [ECMAScript 6](http://www.ecma-international.org/ecma-262/6.0/) as well. Few ECMAScript 6 features like `let` and `const` are available in latest JDK 8 updates(40 and above) and we will cover them later in this chapter. |
| 12 | + |
| 13 | +In this chapter, we will cover the following: |
| 14 | + |
| 15 | +* Working with Nashorn command-line |
| 16 | +* Accessing Java classes and methods |
| 17 | +* Working with Java collections |
| 18 | +* Using external JavaScript libraries |
| 19 | +* Writing scripts |
| 20 | +* Using Nashorn from Java code |
| 21 | +* Using Java 8 features like Streams and Lambdas inside JavaScript code |
| 22 | + |
| 23 | + |
| 24 | +## Working with Nashorn command-line |
| 25 | + |
| 26 | +JDK 8 comes bundled with two command-line tools that can be used to work with Nashorn engine. These two command-line tools are `jrunscript` and `jjs`. `jjs` is recommended to be used when working with Nashorn so we will only discuss it. To use `jjs`, you have to add `jjs` to the path. On *nix machines, you can do that adding a symbolic link as shown below. |
| 27 | + |
| 28 | +```bash |
| 29 | +$ cd /usr/bin |
| 30 | +$ ln -s $JAVA_HOME/bin/jjs jjs |
| 31 | +``` |
| 32 | +Windows users can add `$JAVA_HOME/bin` to the path for easy access. |
| 33 | + |
| 34 | +Once you have set the symbolic link you can access `jjs` from your terminal. To check version of `jjs`, run the following command. |
| 35 | + |
| 36 | +```bash |
| 37 | +$ jjs -v |
| 38 | +nashorn 1.8.0_60 |
| 39 | +jjs> |
| 40 | +``` |
| 41 | + |
| 42 | +It will render the version and then show `jjs>` prompt. You can view the full version of `jjs` by using `jjs -fv` command. |
| 43 | + |
| 44 | +To quit the `jjs` shell, you can use `Ctrl-C`. |
| 45 | + |
| 46 | +Once you are inside `jjs`, you can execute any JavaScript code as shown below. |
| 47 | + |
| 48 | +```bash |
| 49 | +jjs> print("learning about Nashorn") |
| 50 | +learning about Nashorn |
| 51 | +``` |
| 52 | + |
| 53 | +You can define functions as shown below. |
| 54 | + |
| 55 | +``` |
| 56 | +jjs> function add(a,b) {return a + b;} |
| 57 | +``` |
| 58 | + |
| 59 | +You can call the add function as shown below. |
| 60 | + |
| 61 | +``` |
| 62 | +jjs> add(5,10) |
| 63 | +15 |
| 64 | +``` |
| 65 | + |
| 66 | +## Accessing Java classes and methods |
| 67 | + |
| 68 | +It is very easy to access Java classes from within Nashorn. Assuming you are inside the `jjs` shell, you can create an instance of HashMap as shown below. |
| 69 | + |
| 70 | +```bash |
| 71 | +jjs> var HashMap = Java.type("java.util.HashMap") |
| 72 | +jjs> var userAndAge = new HashMap() |
| 73 | +jjs> userAndAge.put("shekhar",32) |
| 74 | +null |
| 75 | +jjs> userAndAge.put("rahul",33) |
| 76 | +null |
| 77 | +jjs> userAndAge.get("shekhar") |
| 78 | +32 |
| 79 | +``` |
| 80 | + |
| 81 | +In the code shown above we have used `Java` global object to create HashMap object. `Java` global object has `type` method that takes a string with the fully qualified Java class name, and returns the corresponding `JavaClass` function object. |
| 82 | + |
| 83 | +```bash |
| 84 | +jjs> HashMap |
| 85 | +[JavaClass java.util.HashMap] |
| 86 | +``` |
| 87 | + |
| 88 | +The `var userAndAge = new HashMap()` is used to instantiate `java.util.HashMap` class using the `new` keyword. |
| 89 | + |
| 90 | +You can access values by either calling the `get` method or using the `[]` notation as shown below. |
| 91 | + |
| 92 | +```bash |
| 93 | +jjs> userAndAge["shekhar"] |
| 94 | +32 |
| 95 | +``` |
| 96 | + |
| 97 | +### Accessing static methods |
| 98 | + |
| 99 | +To access static methods you have to first get the Java type using `Java.type` method and then calling method on `JavaClass` function object. |
| 100 | + |
| 101 | +```bash |
| 102 | +jjs> var UUID = Java.type("java.util.UUID") |
| 103 | +jjs> |
| 104 | +jjs> UUID.randomUUID().toString() |
| 105 | +e4242b89-0e94-458e-b501-2fc4344d5498 |
| 106 | +``` |
0 commit comments