nashorn: javascript that doesn’t suck (iljug)
DESCRIPTION
View the video (in Hebrew) on Parleys: http://www.parleys.com/play/537f3dade4b0e9793767cd35 Java 8 introduces a new JavaScript engine called Nashorn. This presentation gives an overview of the new engine, provides some historical context and dives into the implementation details. Originally presented at the Israeli Java User Group (ILJUG) Java 8 launch event on April 28th, 2014.TRANSCRIPT
![Page 1: Nashorn: JavaScript that doesn’t suck (ILJUG)](https://reader035.vdocuments.us/reader035/viewer/2022062405/554f3e0cb4c905cd048b5282/html5/thumbnails/1.jpg)
Nashorn: JavaScript that doesn’t suck
Tomer Gabel, WixILJUG, April 2014
![Page 2: Nashorn: JavaScript that doesn’t suck (ILJUG)](https://reader035.vdocuments.us/reader035/viewer/2022062405/554f3e0cb4c905cd048b5282/html5/thumbnails/2.jpg)
Agenda
• History• Features• Behind the
scenes• Performance• Juggling Act
![Page 3: Nashorn: JavaScript that doesn’t suck (ILJUG)](https://reader035.vdocuments.us/reader035/viewer/2022062405/554f3e0cb4c905cd048b5282/html5/thumbnails/3.jpg)
History
• Existing Rhino engine:– Slow– Non-compliant– Did I mention slow?
• JavaScript since 1998:– Adoption went
through the roof– Technology advances
(V8, SpiderMonkey…)
![Page 4: Nashorn: JavaScript that doesn’t suck (ILJUG)](https://reader035.vdocuments.us/reader035/viewer/2022062405/554f3e0cb4c905cd048b5282/html5/thumbnails/4.jpg)
Nashorn in a nutshell
• Project Nashorn– Started in July 2011– Integrates with JSR-
223– Reference use-case
for JSR-292
• Released with Java 8 in March 2014
![Page 5: Nashorn: JavaScript that doesn’t suck (ILJUG)](https://reader035.vdocuments.us/reader035/viewer/2022062405/554f3e0cb4c905cd048b5282/html5/thumbnails/5.jpg)
Why bother?
Why you care
• Extensibility and scripting– Macro systems (a la
VBA)– Event hooks
• Server-side JavaScript – More on this later
• End-user programmability– Rule engines– Reporting engines/ETL– BPL and workflow
• … and more
Why Oracle cares
• Atwood’s law• Node.js
– A real threat to Java’s server-side growth
• Reference use-case for JSR-292– Drive innovation– Drive optimization– Reference
implementation
![Page 6: Nashorn: JavaScript that doesn’t suck (ILJUG)](https://reader035.vdocuments.us/reader035/viewer/2022062405/554f3e0cb4c905cd048b5282/html5/thumbnails/6.jpg)
Features
• Self-contained• Implements ECMAScript 5.1
– 100% compliant!• Runtime-compiled to bytecode
(no interpreted mode as with Rhino)
• Small: 1.5MB JAR• Fast!
![Page 7: Nashorn: JavaScript that doesn’t suck (ILJUG)](https://reader035.vdocuments.us/reader035/viewer/2022062405/554f3e0cb4c905cd048b5282/html5/thumbnails/7.jpg)
JSR-223 at a glance
import javax.script.*;
ScriptEngineManager manager = new ScriptEngineManager();ScriptEngine nashorn = manager.getEngineByName("nashorn");
nashorn.eval( "print(\"hello world!\");");
![Page 8: Nashorn: JavaScript that doesn’t suck (ILJUG)](https://reader035.vdocuments.us/reader035/viewer/2022062405/554f3e0cb4c905cd048b5282/html5/thumbnails/8.jpg)
Integrating JSR-223
• Injecting state
nashorn.put("name", "Schnitzel McFry"); nashorn.eval( "print(\"hello \" + name + \"!\");");
![Page 9: Nashorn: JavaScript that doesn’t suck (ILJUG)](https://reader035.vdocuments.us/reader035/viewer/2022062405/554f3e0cb4c905cd048b5282/html5/thumbnails/9.jpg)
Integrating JSR-223
• Invoking JavaScript from Java
nashorn.eval( "function hello(name) { " + " print(\"hello \" + name + \"!\");" + "} " );
Invocable context = (Invocable) nashorn; context.invokeFunction("hello", "world");
![Page 10: Nashorn: JavaScript that doesn’t suck (ILJUG)](https://reader035.vdocuments.us/reader035/viewer/2022062405/554f3e0cb4c905cd048b5282/html5/thumbnails/10.jpg)
Nashorn Extensions
• Java object– Java.type– Java.extend– Java.from– Java.to– Java.super
• A bunch more
![Page 11: Nashorn: JavaScript that doesn’t suck (ILJUG)](https://reader035.vdocuments.us/reader035/viewer/2022062405/554f3e0cb4c905cd048b5282/html5/thumbnails/11.jpg)
Integrating JSR-223
• Invoking Java from JavaScript
nashorn.eval( "var HashMap = Java.type(\"java.util.HashMap\");" + "var map = new HashMap(); " + "map.put(\"name\", \"Schnitzel\"); " + "map.put(\"surname\", \"McFry\"); " );
HashMap<String, String> map = (HashMap<String, String>) nashorn.get("map");
![Page 12: Nashorn: JavaScript that doesn’t suck (ILJUG)](https://reader035.vdocuments.us/reader035/viewer/2022062405/554f3e0cb4c905cd048b5282/html5/thumbnails/12.jpg)
Integrating JSR-223
• Implementing a Java interface
nashorn.eval( "var runnable = { " + " \"run\": function() { print(\"hello world\"); }" + "} " );
Invocable invocable = (Invocable) nashorn;Runnable runnable = invocable.getInterface( nashorn.get("runnable"), Runnable.class);
![Page 13: Nashorn: JavaScript that doesn’t suck (ILJUG)](https://reader035.vdocuments.us/reader035/viewer/2022062405/554f3e0cb4c905cd048b5282/html5/thumbnails/13.jpg)
Integrating JSR-223
• Single Abstract Method (SAM) promotion:
nashorn.eval( "var Thread = Java.type(\"java.lang.Thread\");" + "var thread = new Thread(function() { " + " print(\"hello world\"); " + "} ); " );Thread thread = (Thread) nashorn.get("thread");thread.start();thread.join();
![Page 14: Nashorn: JavaScript that doesn’t suck (ILJUG)](https://reader035.vdocuments.us/reader035/viewer/2022062405/554f3e0cb4c905cd048b5282/html5/thumbnails/14.jpg)
Behind the Scenes
![Page 15: Nashorn: JavaScript that doesn’t suck (ILJUG)](https://reader035.vdocuments.us/reader035/viewer/2022062405/554f3e0cb4c905cd048b5282/html5/thumbnails/15.jpg)
The challenge
• JavaScript is dynamic– Things can change at runtime– Optimization is all about
assumptions
![Page 16: Nashorn: JavaScript that doesn’t suck (ILJUG)](https://reader035.vdocuments.us/reader035/viewer/2022062405/554f3e0cb4c905cd048b5282/html5/thumbnails/16.jpg)
The challenge
• JavaScript is dynamic– Things can change at runtime– Optimization is all about
assumptions• For example, what is the type of:var x = 500000;
![Page 17: Nashorn: JavaScript that doesn’t suck (ILJUG)](https://reader035.vdocuments.us/reader035/viewer/2022062405/554f3e0cb4c905cd048b5282/html5/thumbnails/17.jpg)
The challenge
• JavaScript is dynamic– Things can change at runtime– Optimization is all about
assumptions• For example, what is the type of:var x = 500000;x *= 500000; And now?
![Page 18: Nashorn: JavaScript that doesn’t suck (ILJUG)](https://reader035.vdocuments.us/reader035/viewer/2022062405/554f3e0cb4c905cd048b5282/html5/thumbnails/18.jpg)
The challenge
• JavaScript is dynamic– Things can change at runtime– Optimization is all about
assumptions• For example, what is the type of:var x = 500000;x *= 500000; And now?
• How would you implement this?
![Page 19: Nashorn: JavaScript that doesn’t suck (ILJUG)](https://reader035.vdocuments.us/reader035/viewer/2022062405/554f3e0cb4c905cd048b5282/html5/thumbnails/19.jpg)
The challenge
• Naïve multiplication operator:– Receive LHS and RHS as Objects– Unbox– Test for potential over/underflow– Add via appropriate codepath– Box and return
• You can specialize via static analysis• … but on-the-fly optimization is
better
![Page 20: Nashorn: JavaScript that doesn’t suck (ILJUG)](https://reader035.vdocuments.us/reader035/viewer/2022062405/554f3e0cb4c905cd048b5282/html5/thumbnails/20.jpg)
The challenge
• That’s just one example.– Dynamic
dispatch– Type coercions – Primitive
widening– Prototype
mutation• All of these per
call site!
function square(x) { return x * x;}
square(10) //== 100square(3.14) //== 9.8596square("wat") //== NaN
![Page 21: Nashorn: JavaScript that doesn’t suck (ILJUG)](https://reader035.vdocuments.us/reader035/viewer/2022062405/554f3e0cb4c905cd048b5282/html5/thumbnails/21.jpg)
The challenge
• Runtime code manipulation is not the JVM’s strong suite– Can only load entire classes– High overhead– Hard PermGen space limit– Class unloading issues
![Page 22: Nashorn: JavaScript that doesn’t suck (ILJUG)](https://reader035.vdocuments.us/reader035/viewer/2022062405/554f3e0cb4c905cd048b5282/html5/thumbnails/22.jpg)
Enter JSR 292
• Based on an experimental project, the Da Vinci Machine
• Adds two new concepts to the JVM:– invokedynamic bytecode
instruction– MethodHandles
• The first bytecode extension since 1999!
![Page 23: Nashorn: JavaScript that doesn’t suck (ILJUG)](https://reader035.vdocuments.us/reader035/viewer/2022062405/554f3e0cb4c905cd048b5282/html5/thumbnails/23.jpg)
invokedynamic
• The name is misleading
• It’s not about invocation
• … but about runtime linkage
![Page 24: Nashorn: JavaScript that doesn’t suck (ILJUG)](https://reader035.vdocuments.us/reader035/viewer/2022062405/554f3e0cb4c905cd048b5282/html5/thumbnails/24.jpg)
java.lang.invoke
• MethodHandle– An immutable
function pointer– Composable:
• Guards• Exception
handlers• Argument
mutation– Typesafe andJIT-optimizable
• CallSite– Optionally
mutable wrapper– Binds an
invokedynamic callsite to a target MethodHandle
![Page 25: Nashorn: JavaScript that doesn’t suck (ILJUG)](https://reader035.vdocuments.us/reader035/viewer/2022062405/554f3e0cb4c905cd048b5282/html5/thumbnails/25.jpg)
Why is this cool?
• Generated code is linked at runtime
• Code is hotswappable– Guards for branching
(over/underflow)– SwitchPoints for hotswap
(promotions)• Hotswapping is lightweight
– No class generation or loading• Resulting codepath can be JITted
![Page 26: Nashorn: JavaScript that doesn’t suck (ILJUG)](https://reader035.vdocuments.us/reader035/viewer/2022062405/554f3e0cb4c905cd048b5282/html5/thumbnails/26.jpg)
Don’t forget JEP 122
• The PermGen space is no more– Now called “Metaspace”– Resides in native heap– Block allocator and classloader
isolation– Dynamic size (with bounds)
• Maximum size (hard)• Low/high watermark for GC
• This applies to all GCs (not just G1)
![Page 27: Nashorn: JavaScript that doesn’t suck (ILJUG)](https://reader035.vdocuments.us/reader035/viewer/2022062405/554f3e0cb4c905cd048b5282/html5/thumbnails/27.jpg)
Dynalink
• An open-source library• Builds on top of invokedynamic:
– Metaobject protocol– Linkage model
• Enables cross-language interop (JRuby, Jython, Nashorn, plain Java)
• Open source (Apache-licensed)
![Page 28: Nashorn: JavaScript that doesn’t suck (ILJUG)](https://reader035.vdocuments.us/reader035/viewer/2022062405/554f3e0cb4c905cd048b5282/html5/thumbnails/28.jpg)
So how does it perform?
![Page 29: Nashorn: JavaScript that doesn’t suck (ILJUG)](https://reader035.vdocuments.us/reader035/viewer/2022062405/554f3e0cb4c905cd048b5282/html5/thumbnails/29.jpg)
Pretty damn good!
• 2-10 times faster than Rhino• ~60% percent of V8• Not much research out there
![Page 30: Nashorn: JavaScript that doesn’t suck (ILJUG)](https://reader035.vdocuments.us/reader035/viewer/2022062405/554f3e0cb4c905cd048b5282/html5/thumbnails/30.jpg)
Avatar.js
• Implements the Node model and API on the JVM
• Supports most modules– Some natively– Some via JNI
• … and it does work!
Supported module highlights• mocha• coffee-script• uglify-js• underscore• request• async• jade• express• mongodb• Redis
Most popular per nodejsmodules.org
![Page 31: Nashorn: JavaScript that doesn’t suck (ILJUG)](https://reader035.vdocuments.us/reader035/viewer/2022062405/554f3e0cb4c905cd048b5282/html5/thumbnails/31.jpg)
QUESTIONS?Thank you!
![Page 32: Nashorn: JavaScript that doesn’t suck (ILJUG)](https://reader035.vdocuments.us/reader035/viewer/2022062405/554f3e0cb4c905cd048b5282/html5/thumbnails/32.jpg)
Thank you!Additional reading:• Nashorn war stories
(from a battle scarred veteran of invokedynamic)
• Dynalink
Contact me:• http://www.tomergabel.c
om• [email protected]• @tomerg