Highly Efficient Java & JavaScript Integration

Highly Efficient Java & JavaScript Integration

Over the past 4 months I’ve been working on integrating Java and JavaScript in a highly efficient manner. Rhino and Nashorn are two common JavaScript runtimes, but these did not meet our requirements in a number of areas:

  • Neither support ‘Primitives‘. All interactions with these platforms require wrapper classes such as Integer, Double or Boolean.
  • Nashorn is not supported on Android.
  • Rhino compiler optimizations are not supported on Android.
  • Neither engines support remote debugging on Android.

To help address these issues, I’ve built a new JavaScript runtime for Java based on Google’s JavaScript Engine, V8. The runtime, called J2V8, is open sourced under the EPL and available on GitHub. I’ve been running it on MacOS, Linux and Android.

Unlike other JS Runtimes (including JV8, Jav8), J2V8 takes a primitive based approach, resulting in much less garbage. The following script produces an array containing the first 100 fibonacci numbers. Each of these numbers can be accessed directly, without the need for wrapper objects. Executing this script 10,000 times on Rhino takes 7.5 seconds. The same script runs 10,000 times on J2V8 in under 1 second.

<pre lang="JavaScript">var i;
var fib = []; //Initialize array!

fib[0] = 1;
fib[1] = 1;
for(i=2; i<=100; i++)
{
    fib[i] = fib[i-2] + fib[i-1];
}
fib;</pre>

Fibonacci in JavaScript

<pre lang="Java">V8Array array = v8.executeArrayScript(script);
double total = 0;
for (int i = 0; i < 100; i++) {
  total += array.getDouble(i);
}
System.out.println(total);
array.release();</pre>

Accessing JS Arrays in Java

The runtime was built by exposing parts of the V8 API through a thin JNI bridge. This approach allows you to embed V8 directly into Java applications without the use of C/C++. J2v8 currently targets V8 version 3.26, but I’ll be updating that to a more recent build soon.

The runtime currently supports V8Objects, V8Arrays, invoking scripts, calling JS functions from Java and registering Java Functions as callbacks from JS. There is also a small library for converting V8Objects and V8Arrays to Java Maps and Lists. Finally, the runtime supports remote debugging and can be utilized with tools such as Chrome Developer Tools for Eclipse.

Screen Shot 2014-11-14 at 2.41.40 PM
Over the next few weeks I’ll be publishing builds and putting together a getting started guide. If you are interested in this project, please let me know or ping me on twitter.

8 Comments
  • Angelo
    Posted at 9:36 am, November 17, 2014

    Thank’s for sharing your project.

    In tern.java https://github.com/angelozerr/tern.java I execute the JavaScript inference engine tern.js with node.js (Java client communicate with node.js server which starts tern.js).

    I had tested Rhino, and they were a lot of problem with memory and performance because tern.js creates a lot of JS object.

    Today node.js works very well, but I tell me if J2V8 could support tern.js? tern.java provides some API to implement tern server (today it exists Rhino, and Node.js), perhaps J2V8 could be implemented too?

  • Guillermo Zunino
    Posted at 4:21 pm, November 17, 2014

    Hi, great work!
    Is this available as an osgi bundle on a p2 repository?

  • Niko
    Posted at 11:42 am, November 18, 2014

    So you are comparing apples and oranges while comparing the performance of J2V8 with Rhino. Interesting would only be a comparison to Nashorn. Rhino is old and slow, everybody knows that… And, additionally it becomes interesting with the next Java 8u40 release, there are massive performance improvements for Nashorn.
    What about a comparison to DynJS?

    Other question:
    Is it possible to access Java classes/objects from J2V8 like it is with Nashorn?

  • mblinky
    Posted at 4:38 pm, November 26, 2014

    Very interested! But yeh need documentation.

    I cloned in eclipse and got “…missing required source folder: ‘src/main/resources’. I created the folder manually, which got rid of the build error, and ran the tests and all failed with trace starting with

    java.lang.IllegalStateException: J2V8 native library not loaded.

    These are probably dumb newbie mistakes. But even just documentation of “How to build it and run the tests” would be very useful!

  • mblinky
    Posted at 5:14 pm, November 26, 2014

    Note: I’m on Windows 7, using Eclipse Kepler, Java 7. I assume i have to build using build.sh, but the command clang++ isn’t recognized. I assume that builds V8? I have an installation of V8 locally — can i use that?

  • mblinky
    Posted at 5:55 pm, December 1, 2014

    OK, so my last comment was bogus as I now see (having installed clang and run build.sh), since the build was for your local environment. Fair enough. My dumb misread. However, the bottom line is that your project doesn’t run as is in a Window 7/ Kepler environment. Not sure how it would run in any environment unless there are prerequisites that you have not specified.

    When I try to run any tests, I get

    Caused by: java.lang.UnsatisfiedLinkError: no j2v8 in java.library.path

    Which, looking at your code, makes sense because … there is no “j2v8” library to load!

    Please provide some documentation. At least: a) what are the prereqs?; b) What platforms does it NOT work on?; c) how to install and hello world.

    Thx.

  • Eric
    Posted at 1:39 pm, January 19, 2015

    Hi Ian,

    This looks interesting. I’m no expert, but I’m trying to find some way to call Julia from Java for numerical modelling. I recently learned about Nashorn and was hoping I could get node-julia to work with it, but alas, node-julia depends on native v8.

    A bit of searching brought me here. Is it possible that with J2V8 or something like it, we can get node-julia working? Is there a better way to access Julia functionality from within Java?

    Best regards