Running JavaScript Efficiently in a Java World

28
J2V8 Running JavaScript Efficiently in a Java World R. Ian Bull EclipseSource @irbull

Transcript of Running JavaScript Efficiently in a Java World

Page 1: Running JavaScript Efficiently in a Java World

J2V8 Running JavaScript Efficiently in a Java World

R. Ian BullEclipseSource

@irbull

Page 2: Running JavaScript Efficiently in a Java World

Are You a JavaScript Developer?• This talk is not for you. But you’ll want this information!

• Running JavaScript in Java environments

• Optimizing JavaScript for Java deployment

• Java concepts bleeding into JavaScript

• Can we unleash performant JavaScript in a Java System?

Page 3: Running JavaScript Efficiently in a Java World

Example — Tabris.js• Mobile framework

• Apps written in JavaScript

• Native iOS and Android Apps

• Bindings to native UI components

• JavaScript was fast, Java was slow

Page 4: Running JavaScript Efficiently in a Java World

Tabris.js

• Tight integration between the mobile platform and JS

Page 5: Running JavaScript Efficiently in a Java World

Android and JS• Android bindings written in Java

• No decent Java / JavaScript integration on Android

• Nashorn is not available

• Rhino slooooow

Page 6: Running JavaScript Efficiently in a Java World

What About V8?

• V8 is a highly performant Javascript runtime

• Written entirely in C++

• Workhorse behind node.js & Chromehttp://ariya.ofilabs.com/2014/03/nashorn-the-new-rhino-on-the-block.html

Page 7: Running JavaScript Efficiently in a Java World

J2V8• Can we leverage V8 for Android development?

• Create a thin JNI layer above V8

• Expose V8 API in Java

• Open Source

Page 8: Running JavaScript Efficiently in a Java World

J2V8 Design• C++ (JNI) Bindings between Java & JavaScript

• Two GCs and unmanaged memory model in the middle

V8

J2V8 — C++

Java I Live Here

Page 9: Running JavaScript Efficiently in a Java World

J2V8 Design• Make JavaScript shine in an enterprise Java World

• Standard Java APIs

• Efficient Java / JavaScript bindings

• No Java system knowledge in JavaScript

• Multithreaded Java & JavaScript integration

Page 10: Running JavaScript Efficiently in a Java World

Script Execution Example (Java)

public static void main(String[] args) {

V8 v8 = V8.createV8Runtime(); Object result = v8.executeScript("1+1"); System.out.println("Result: " + result); v8.release();

}

Page 11: Running JavaScript Efficiently in a Java World

Script Execution Example (JavaScript)

Page 12: Running JavaScript Efficiently in a Java World

JavaScript Objects• Access JavaScript objects from Java

• No special JS required

• Object are lazily copied to Java

v8.executeScript("person = {name : {first : 'john', last:'smith'} };");

String name = v8.get(“person”).get(“name”).get(“first”);

Page 13: Running JavaScript Efficiently in a Java World

Lists and Maps Utilities• Working with V8Objects is highly performant but complex

• Access JSObjects using java.util

• JavaScript Object mapped to java.util.Map

• JavaScript Array mapped to java.util.List

• In short: It works with common Java API

Page 14: Running JavaScript Efficiently in a Java World

Calling JS Functions• JavaScript Functions can be called from Java

• Use the results directly in Java

• Java Methods can be called from JavaScript

• Pass JavaScript Objects to Java

Page 15: Running JavaScript Efficiently in a Java World

Calling JavaScript• Any Java Method can be registered as a Function

• Call the Function as you would any other Function

• Java Methods can be specified with ‘var args’

JavaCallback callback = new MyJavaCallback(); v8.registerJavaMethod(callback, “foo");

v8.executeScript(“foo(‘a’, false, undefined)”);

Page 16: Running JavaScript Efficiently in a Java World

JavaScript Exceptions

• JavaScript errors / exceptions propagate to Java

Page 17: Running JavaScript Efficiently in a Java World

Typed Arrays

V8Array result = (V8Array) v8.executeScript("" + "var buf = new ArrayBuffer(100);" + "var ints = new Int32Array(buf); " + "for(var i = 0; i < 25; i++) {" + " ints[i] = i;" + "}; " + “ints");

int[] ints = result.getIntegers(0, 25);

• Native support for JS Typed Arrays

• Access the values efficiently from Java

Page 18: Running JavaScript Efficiently in a Java World

Workers• Supports multi-threaded JavaScript execution

• Implemented as Java Threads

• Each JS Script runs in its own ‘Isolate’

• Can send messages between threads

Page 19: Running JavaScript Efficiently in a Java World

Debugger Support

• J2V8 can listen on a port for debug events

Page 20: Running JavaScript Efficiently in a Java World

Performancevar data = [];for (var i = 0; i < 100000; i++) {

data[i] = i;

}

for ( var i = 0; i < data.length; i++) {

for ( var j = 0; j < data.length; j++ ) {

if ( data[i] < data[j] ) {

var tmp = data[i];

data[i] = data[j];

data[j] = tmp;

}

}

}

Page 21: Running JavaScript Efficiently in a Java World

Performance

V8 Nashorn Rhino

Rhino: ???Nashorn 2:30J2V8 0:13

Page 22: Running JavaScript Efficiently in a Java World

Performance Considerations• Minimize callbacks from JavaScript to Java

• ~4000 Per Second on my MBP

• Use bulk array copy to move primitives from JS to Java

• 60fps in our animation demo

Page 23: Running JavaScript Efficiently in a Java World

Tern• Tern is a stand-alone code-analysis engine for JavaScript

• Moved to J2V8 for Java integration

Page 24: Running JavaScript Efficiently in a Java World

Building V8• Embeds V8 in the .jar file

• V8 built for each platform we support

• Build instructions encoded as a docker file

[%] git clone https://github.com/eclipsesource/J2V8.git[%] docker build --rm=true --no-cache -t "eclipsesource/v8-build" .

Page 26: Running JavaScript Efficiently in a Java World

Future Work• Script API (JSR 223)

• Advanced exception handling between Java and JS

• Batch callbacks for better JNI performance

• Debugger integration with Chrome Dev Tools

Page 27: Running JavaScript Efficiently in a Java World

Using J2V8• J2V8 is available in Maven Central

• Currently 5 variants are available:

com.eclipsesource.j2v8.j2v8_win32_x86:2.2.1 com.eclipsesource.j2v8.j2v8_macosx_x86_64:2.2.1com.eclipsesource.j2v8.j2v8_android:2.2.1com.eclipsesource.j2v8.j2v8_android_armv7l:2.2.1com.eclipsesource.j2v8.j2v8_android_x86:2.2.1

• j2v8_android:2.0 contains both x86 and armv7l, and the correct library will be selected at runtime

Page 28: Running JavaScript Efficiently in a Java World

J2V8• Open Source Java bindings for V8

• Licensed under the EPL

• For J2V8 news, follow me on Twitter @irbull

https://github.com/eclipsesource/j2v8