GraalWasm is an open-source WebAssembly runtime compatible with the WebAssembly 1.0 specification. It runs WebAssembly programs in binary format and can be used to embed and leverage WebAssembly modules in Java applications.
GraalWasm is in active development and implements a number of WebAssembly feature extensions. Feedback, bug reports, and contributions are welcome.
GraalWasm can be used via the GraalVM SDK Polyglot API, which allows embedding WebAssembly modules into Java applications.
GraalVM SDK Polyglot API can be easily added as a Maven dependency to your Java project. The GraalWasm artifact should be on the Java module or class path too.
Add the following set of dependencies to the project configuration file (pom.xml in the case of Maven).
- To add the Polyglot API:
<dependency> <groupId>org.graalvm.polyglot</groupId> <artifactId>polyglot</artifactId> <version>${graalwasm.version}</version> </dependency>
- To add GraalWasm:
<dependency> <groupId>org.graalvm.polyglot</groupId> <artifactId>wasm</artifactId> <version>${graalwasm.version}</version> </dependency>
- To add Truffle tools:
<dependency> <groupId>org.graalvm.polyglot</groupId> <artifactId>tools</artifactId> <version>${graalwasm.version}</version> </dependency>
Now you can embed WebAssembly in your Java application. For example, assuming you have the following C program:
#include <stdio.h>
void floyd() {
int number = 1;
int rows = 10;
for (int i = 1; i <= rows; i++) {
for (int j = 1; j <= i; j++) {
printf("%d ", number);
++number;
}
printf(".\n");
}
}
int main() {
floyd();
return 0;
}
The floyd
function is defined as separate and can be later exported.
-
Compile floyd.c using the most recent version of the Emscripten compiler frontend:
emcc --no-entry -s EXPORTED_FUNCTIONS=_floyd -o floyd.wasm floyd.c
The exported functions must be prefixed by
_
. If you reference that function in Java code, the exported name should not contain the underscore.It produces a standalone floyd.wasm file in the current working directory.
-
Use the Polyglot API to load the WebAssembly module and access its exported functions.
try (Context context = Context.newBuilder("wasm").option("wasm.Builtins", "wasi_snapshot_preview1").build()) { // Evaluate the WebAssembly module Source source = Source.newBuilder("wasm", new File("path/to/floyd.wasm")).name("example").build(); context.eval(source); // Initialize the module and execute the floyd function Value exampleModule = context.getBindings("wasm").getMember("example"); exampleModule.getMember("_initialize").executeVoid(); Value floydFunction = exampleModule.getMember("floyd"); floydFunction.execute(); }
GraalWasm is also available as a standalone distribution.
-
Download the distribution for your operating system:
- Native standalone
- JVM standalone
-
Unzip the archive:
Note: If you are using macOS Catalina and later you may need to remove the quarantine attribute:
sudo xattr -r -d com.apple.quarantine <archive>.tar.gz
Extract:
tar -xzf <archive>.tar.gz
-
The standalone runtime comes with a JVM in addition to its native launcher. Check the version to see if it is active:
./path/to/bin/wasm --version
Now you have the launcher which can run WebAssembly programs directly.
-
Compile floyd.c from the example above using the most recent version of the Emscripten compiler frontend:
$ emcc -o floyd.wasm floyd.c
It produces a standalone floyd.wasm file in the current working directory.
-
Now you can run the compiled WebAssembly binary as follows:
$ ./path/to/bin/wasm --Builtins=wasi_snapshot_preview1 floyd.wasm
The option
--Builtins
specifies built-in modules that the Emscripten toolchain assumes.
You can also use the WASI SDK toolchain to compile C programs into WebAssembly modules and run them on GraalWasm (either embedded through the Polyglot API or using the launcher).
-
Download the
wasi-sdk
and unpack it. -
Set
WASI_SDK
:$ export WASI_SDK=[path to wasi-sdk]
-
Compile the C files:
$ $WASI_SDK/bin/clang -O3 -o test.wasm test.c
To export a specific function use the linker flag
-Wl,--export="[function name]"
. -
Most applications compiled with the wasi-sdk require WASI. To run a file with WASI enabled use the following command:
$ ./bin/wasm --Builtins=wasi_snapshot_preview1 test.wasm
GraalWasm is licensed under the Universal Permissive License.