Announcing the first Java library to run WebAssembly: Wasmer JNI

Ivan Enderlin
May 13, 2020 · 5 min read

WebAssembly is a portable binary format. That means the same file can run anywhere.

To uphold this bold statement, each language, platform and system must be able to run WebAssembly — as fast and safely as possible.

People who are familiar with Wasmer are used to this kind of announcement! Wasmer is written in Rust, and comes with an additional native C API. But you can use it in a lot of other languages. After having announced libraries to use Wasmer, and thus WebAssembly, in:

…we are jazzed to announce that Wasmer has now landed in Java!

Let’s discover the Wasmer JNI library together.

Installation

The Wasmer JNI (Java Native Interface) library is based on the Wasmer runtime, which is written in Rust, and is compiled to a shared library. For your convenience, we produce one JAR (Java Archive) per architecture and platform. By now, the following are supported, consistently tested, and pre-packaged (available in Bintray and Github Releases):

  • amd64-darwin for macOS, x86 64bits,
  • amd64-linux for Linux, x86 64 bits,
  • amd64-windows for Windows, x86 64 bits.

More architectures and more platforms will be added in the near future. If you need a specific one, feel free to ask! However, it is possible to produce your own JAR for your own platform and architecture.

The JAR files are named as follows: wasmer-jni-$(architecture)-$(os)-$(version).jar. Thus, to include Wasmer JNI as a dependency of your project (assuming you use Gradle), write for instance:

dependencies {
implementation "org.wasmer:wasmer-jni-amd64-linux:0.2.0"
}

JAR are hosted on the Bintray/JCenter repository under the wasmer-jni project. They are also attached to our Github releases as assets.

Calling a WebAssembly function from Java

As usual, let’s start with a simple Rust program that we will compile to WebAssembly, and then execute from Java.

simple.rs, a small Rust program that compiles to WebAssembly.

After compilation to WebAssembly, we get a file like this one, named simple.wasm.

The following Java program executes the sum exported function by passing 5 and 37 as arguments:

Baby-steps to execute WebAssembly in Java.

Great! We have successfully executed a Rust program, compiled to WebAssembly, in Java. As you can see, it is pretty straightforward. The API is very similar to the standard JavaScript API, or the other API we have designed for PHP, Python, Go, Ruby etc.

The assiduous reader might have noticed the [0] in .apply(5, 37)[0] pattern. A WebAssembly function can return zero to many values, and in this case, we are reading the first one.

Note: Java values passed to WebAssembly exported functions are automatically downcasted to WebAssembly values. Types are inferred at runtime, and casting is done automatically. Thus, a WebAssembly function acts as any regular Java function.

Technically, an exported function is a functional interface as defined by the Java Language Specification (i.e. it is a FunctionalInterface). Thus, it is possible to write the following code where sum is an actual function (of kind org.wasmer.exports.Function):

Use WebAssembly exported function as any regular Java function.

But a WebAssembly module not only exports functions, it also exports memory.

Reading the memory

A WebAssembly instance has one or more linear memories, a contiguous and byte-addressable range of memory spanning from offset 0 and extending up to a varying memory size, represented by the org.wasmer.Memory class. Let’s see how to use it. Consider the following Rust program:

A Rust program returning a statically allocated string.

The return_hello function returns a pointer to the statically allocated string. The string exists in the linear memory of the WebAssembly module. It is then possible to read it in Java:

Reading the WebAssembly memory in Java.

As we can see, the Memory API provides a buffer method. It returns a direct byte buffer (of kind java.nio.ByteBuffer) view of the memory. It’s a standard API for any Java developer. We think it’s best to not reinvent the wheel and use standard API as much as possible.

The WebAssembly memory is dissociated from the JVM memory, and thus from the garbage collector.

You can read the Greet Example to see a more in-depth usage of the Memory API.

More documentation

The project comes with a Makefile. The make javadoc command will generate a traditional local Javadoc for you, in the build/docs/javadoc/index.html file.

In addition, the project’s README.md file has an API of the wasmer library Section.

Finally, the project comes with a set of examples. Use the make run-example EXAMPLE=Simple to run the SimpleExample.java example for instance.

Performance

WebAssembly aims at being safe, but also fast. Since Wasmer JNI is the first Java library to execute WebAssembly, we can’t compare to prior works in the Java ecosystem. However, you might know that Wasmer comes with 3 backends: Singlepass, Cranelift and LLVM. We’ve even written an article about it: A WebAssembly Compiler tale. The Wasmer JNI library uses the Cranelift backend for the moment, which offers the best compromise between compilation-time and execution-time.

Credits

Asami (d0iasm on Twitter) has improved this project during its internship at Wasmer under my guidance. She finished the internship before the release of the Wasmer JNI project, but she deserves credits for pushing the project forward! Good work Asami!

This is an opportunity to remind everyone that we hire anywhere in the world. Asami was working from Japan while I am working from Switzerland, and the rest of the team is from US, Spain, China etc. Feel free to contact me (@mnt_io or @syrusakbary on Twitter) if you want to join us on this big adventure!

Conclusion

Wasmer JNI is a library to execute WebAssembly directly in Java. It embeds the WebAssembly runtime Wasmer. The first releases provide the core API with Module, Instance, and Memory. It comes pre-packaged as a JAR, one per architecture and per platform.

The source code is open and hosted on Github at https://github.com/wasmerio/java-ext-wasm. We are constantly improving the project, so if you have feedback, issues, or feature requests please open an issue in the repository, or reach us on Twitter at @wasmerio or @mnt_io.

We look forward to see what you build with this!

Wasmer

Universal WebAssembly runtime

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store