Wasmer is a Java library for executing WebAssembly binaries:
wasmer API mimics the standard WebAssembly API,wasmer executes the WebAssembly modules as fast as possible,Need these tools in your environment:
First, you need to download this project, and make wasmer-0.1.jar and libjava_ext_wasm.so by the just package command. wasmer-0.1.jar is the JAR file to contains Java interface for Wasmer. libjava_ext_wasm.so is the shared library of Wasmer (.dylib on macOS, .so on Linux, .dll on Windows).
// Download java-ext-wasm. $ git clone https://github.com/wasmerio/java-ext-wasm/ $ cd java-ext-wasm // Build the project and make a JAR file. $ just package
You need to copy both files from wasmer-0.1.jar in the java/target directory and libjava_ext_wasm.so in the target/release directory to your project. Then, install a JAR file to your project, compile your Java source code, and execute it with the path which a shared library exists.
// Install a Wasmer plugin to our project. $ mvn install:install-file -Dfile=wasmer-0.1.jar // Compile java source files. $ mvn compile // Execute our project with the library path. $ MAVEN_OPTS=-Djava.library.path=. mvn exec:java
This is overall steps to execute your Java project with java-ext-wasm. For more information, you can see the example project.
There is a toy program in java/src/test/resources/simple.rs, written in Rust (or any other language that compiles to WebAssembly):
#[no_mangle] pub extern fn sum(x: i32, y: i32) -> i32 { x + y }
After compilation to WebAssembly, the java/src/test/resources/simple.wasm binary file is generated. (Download it).
Then, we can execute it in Java:
class Example { public static void main(String[] args) { // simple.wasm is located at src/main/resources/. Path wasmPath = Paths.get(new Example().getClass().getClassLoader().getResource("simple.wasm").getPath()); // Reads the WebAssembly module as bytes. byte[] wasmBytes = Files.readAllBytes(wasmPath); // Instantiates the WebAssembly module. Instanace = new Instance(wasmBytes); // Calls an exported function, and returns an object array. Object[] results = instance.exports.get("sum").apply(5, 37); System.out.println((Integer) results[0]); // 42 // Drops an instance object pointer which is stored in Rust. instance.close(); } }
wasmer libraryInstance classThe Instance constructor compiles and instantiates a WebAssembly module. It is built upon bytes. From here, it is possible to call exported functions, or exported memories. For example:
// Instantiates the WebAssembly module. Instance instance = new Instance(wasmBytes); // Calls an exported function. Object[] results = instance.exports.get("sum").apply(1, 2); // Casts an object to an integer object because the result is an object array. int result = (Integer) results[0]; System.out.println(result); // 3 // Drops an instance object pointer manually. Note that the garbage collector // will call this method before an object is removed from the memory. instance.close();
All exported functions are accessible on the Instance.exports field in the Instance class. The get method allows to get a single exported function by its name. An exported function is a Java closure, where all arguments are automatically casted to WebAssembly values if possible, and all results are of type Object, which can be typed to Integer or Float for instance.
Exports exportedFunctions = instance.exports; ExportedFunction sum = exportedFunctions.get("sum"); Object[] results = sum.apply(1, 2); System.out.println((Integer) results[0]); // 3
The Instance.memories field exposes the Memories class representing the set of memories of that particular instance, e.g.:
Memories memories = instance.memories;
See the Memory class section for more information.
Module classThe Module.validate static method checks whether a sequence of bytes represents a valid WebAssembly module:
// Checks that given bytes represent a valid WebAssembly module. boolean isValid = Module.validate(wasmBytes);
The Module constructor compiles a sequence of bytes into a WebAssembly module. From here, it is possible to instantiate it:
// Compiles the bytes into a WebAssembly module. Module module = new Module(wasmBytes); // Instantiates the WebAssembly module. Instance instance = module.instantiate();
The Module.serialize method and its complementary Module.deserialize static method help to respectively serialize and deserialize a compiled WebAssembly module, thus saving the compilation time for the next use:
// Compiles the bytes into a WebAssembly module. Module module1 = new Module(wasmBytes); // Serializes the module. byte[] serializedModule = module1.serialize(); // Let's forget about the module for this example. module1 = null; // Deserializes the module. Module module2 = Module.deserialize(serializedModule); // Instantiates and uses it. Object[] results = module2.instantiate().exports.get("sum").apply(1, 2); System.out.println((Integer) results[0]); // 3
Memory classA WebAssembly instance has a linear memory, represented by the Memory class. Let's see how to read it. Consider the following Rust program:
#[no_mangle] pub extern fn return_hello() -> *const u8 { b"Hello, World!\0".as_ptr() }
The return_hello function returns a pointer to a string. This string is stored in the WebAssembly memory. Let's read it.
Instance instance = new Instance(wasmBytes); // Gets the memory by specifing its exported name. Memory memory = instance.memories.get("memory"); // Gets the pointer value as an integer. int pointer = (Integer) instance.exports.get("return_hello").apply()[0]; // Reads the data from the memory. byte[] stringBytes = memory.read(pointer, 13); System.out.println(new String(stringBytes)); // Hello, World! instance.close();
The Memory.grow methods allows to grow the memory by a number of pages (of 64KiB each).
// Grows the memory by the specified number of pages, and returns the number of old pages. int oldPageSize = memory.grow(1);
You need just to build the project.
To build Java parts, run the following command:
$ just build-java
To build Rust parts, run the following command:
$ just build-rust
To build the entire project, run the following command:
$ just build
Run the following command:
$ just test
Testing automatically build the project.
Quoting the WebAssembly site:
WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable target for compilation of high-level languages like C/C++/Rust, enabling deployment on the web for client and server applications.
About speed:
WebAssembly aims to execute at native speed by taking advantage of common hardware capabilities available on a wide range of platforms.
About safety:
WebAssembly describes a memory-safe, sandboxed execution environment […].
The entire project is under the MIT License. Please read the LICENSE file.