Nashorn: JavaScript that doesn’t suck (ILJUG)

4,736 views

Published on

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.

Published in: Technology, Education
0 Comments
12 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
4,736
On SlideShare
0
From Embeds
0
Number of Embeds
144
Actions
Shares
0
Downloads
74
Comments
0
Likes
12
Embeds 0
No embeds

No notes for slide

Nashorn: JavaScript that doesn’t suck (ILJUG)

  1. 1. Nashorn: JavaScript that doesn’t suck Tomer Gabel, Wix ILJUG, April 2014
  2. 2. Agenda • History • Features • Behind the scenes • Performance • Juggling Act
  3. 3. History • Existing Rhino engine: – Slow – Non-compliant – Did I mention slow? • JavaScript since 1998: – Adoption went through the roof – Technology advances (V8, SpiderMonkey…)
  4. 4. 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
  5. 5. 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
  6. 6. Features • Self-contained • Implements ECMAScript 5.1 – 100% compliant! • Runtime-compiled to bytecode (no interpreted mode as with Rhino) • Small: 1.5MB JAR • Fast!
  7. 7. JSR-223 at a glance import javax.script.*; ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine nashorn = manager.getEngineByName("nashorn"); nashorn.eval( "print("hello world!");");
  8. 8. Integrating JSR-223 • Injecting state nashorn.put("name", "Schnitzel McFry"); nashorn.eval( "print("hello " + name + "!");");
  9. 9. Integrating JSR-223 • Invoking JavaScript from Java nashorn.eval( "function hello(name) { " + " print("hello " + name + "!");" + "} " ); Invocable context = (Invocable) nashorn; context.invokeFunction("hello", "world");
  10. 10. Nashorn Extensions • Java object – Java.type – Java.extend – Java.from – Java.to – Java.super • A bunch more
  11. 11. 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");
  12. 12. 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);
  13. 13. 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();
  14. 14. Behind the Scenes
  15. 15. The challenge • JavaScript is dynamic – Things can change at runtime – Optimization is all about assumptions
  16. 16. 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;
  17. 17. 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?
  18. 18. 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?
  19. 19. 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
  20. 20. 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) //== 100 square(3.14) //== 9.8596 square("wat") //== NaN
  21. 21. 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
  22. 22. 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!
  23. 23. invokedynamic • The name is misleading • It’s not about invocation • … but about runtime linkage invokedynamic Bootstrap Method Target Call Site Compile-time Runtime Invokes Returns MethodHandle
  24. 24. java.lang.invoke • MethodHandle – An immutable function pointer – Composable: • Guards • Exception handlers • Argument mutation – Typesafe and JIT-optimizable • CallSite – Optionally mutable wrapper – Binds an invokedynamic callsite to a target MethodHandle
  25. 25. 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
  26. 26. 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)
  27. 27. 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)
  28. 28. So how does it perform?
  29. 29. Pretty damn good! • 2-10 times faster than Rhino • ~60% percent of V8 • Not much research out there
  30. 30. 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
  31. 31. QUESTIONS? Thank you!
  32. 32. Thank you! Additional reading: • Nashorn war stories (from a battle scarred veteran of invokedynamic) • Dynalink Contact me: • http://www.tomergabel.com • tomer@tomergabel.com • @tomerg

×