- GraalVM for JDK 23 (Latest)
- GraalVM for JDK 24 (Early Access)
- GraalVM for JDK 21
- GraalVM for JDK 17
- Archives
- Dev Build
GraalWasm
GraalWasm is an open-source WebAssembly runtime. It runs WebAssembly programs in binary format and can be used to embed and leverage WebAssembly modules in Java applications. GraalWasm is under active development and implements a number of WebAssembly extensions.
WebAssembly Module System #
Using GraalWasm, you can load WebAssembly modules in your application, access them from Java, and make them interoperate with other Graal languages. To proficiently use GraalWasm, it is important to first understand how GraalWasm maps WebAssembly’s module system onto the Polyglot API.
GraalWasm uses the binary format of WebAssembly modules as its language. A valid Source that you can evaluate using GraalWasm is always a single WebAssembly module in the binary format.
Here is one way you can build a WebAssembly Source
:
Source source = Source.newBuilder("wasm", new File("example.wasm")).name("example").build();
When you evaluate a WebAssembly Source
, the module is parsed, and validated, and a module instance is returned as the resulting value.
The module instance can also later be retrieved from the top-level bindings.
The name of the binding in the top-level scope is the same as the name of the Source
that was evaluated.
// Evaluate the Source named "example".
Value exampleModule = context.eval(source);
// It is now accessible under the binding name "example".
assert context.getBindings("wasm").getMember("example") == exampleModule;
Source names are important in GraalWasm because they are also used to resolve module imports.
If a module tries to import a symbol from module foo
, then GraalWasm looks for that symbol in the module whose Source
was named foo
.
These imports are not resolved until when a WebAssembly module instance’s members are accessed or executed for the first time in a given context.
Module Instance Objects #
By evaluating WebAssembly modules through the Polyglot API, you get access to module instance objects. Module instance objects expose members for every symbol that was exported from the WebAssembly module. You can get a list of all exported symbols using getMemberKeys, access individual exports using getMember and, in the case of mutable globals, use putMember to set their values.
Here is how the various kinds of WebAssembly exports map to polyglot values:
-
Functions
Functions are exported as executable values, which you can call using execute. Function arguments and return values are mapped between WebAssembly value types and polyglot values using the type mapping. If a function returns multiple values, these are wrapped in an interop array.
-
Globals
When you access an exported global using
getMember
, you get the global’s value, mapped using the type mapping. If the global is mutable, you can also update its value usingputMember
. Currently, setting globals works only for numeric types, whose value is mapped according to the type mapping. -
Memories
Exported memories implement both the array interface and the buffer interface. The array interface lets you view the memory as an array of bytes using getArrayElement and setArrayElement. The buffer interface lets you do bulk copies of memory using readBuffer and read and write the Java primitive types from and to the memory using the
readBuffer*
andwriteBuffer*
methods. -
Tables
Exported tables are opaque and cannot be queried or modified.
Type Mapping #
Whenever a WebAssembly value is passed either to Java code or to another Graal language, via a function call, return value, or exported global access, it is mapped to a polyglot value. The tables below show how this mapping works. WebAssembly is a statically-typed language and all values (locals, function arguments, return values) have a static type. Based on this type, GraalWasm interprets a polyglot value as a value of this type or reports a type error if the types do not match.
WebAssembly Values as Polyglot Values #
This table describes for each WebAssembly value type which polyglot interfaces the resulting value implements.
WebAssembly Type | Polyglot Interface |
---|---|
i32 |
Number that fits in int |
i64 |
Number that fits in long |
f32 |
Number that fits in float |
f64 |
Number that fits in double |
v128 |
Read-only buffer of 16 bytes |
funcref |
Executable object |
externref |
Returned verbatim |
Passing Arguments to WebAssembly Functions #
When calling an exported WebAssembly function, its exact type signature must be respected. The table below gives the expected argument type for every possible WebAssembly parameter type.
WebAssembly Parameter Type | Expected Argument Type |
---|---|
i32 |
int |
i64 |
long |
f32 |
float |
f64 |
double |
v128 |
Existing v128 value received from WebAssembly |
funcref |
WebAssembly’s ref.null or an exported WebAssembly function |
externref |
Can be anything (only WebAssembly’s ref.null is seen as null by ref.is_null ) |
Options #
GraalWasm can be configured with several options. When using the Polyglot API, options are passed programmatically to the Context object:
Context.newBuilder("wasm").option("wasm.Builtins", "wasi_snapshot_preview1").build();
See the Polyglot Programming reference for more information on how to set options programmatically.
The available options are divided into stable and experimental options.
Experimental options are provided with no guarantee of future support and can change from version to version.
If an experimental option is used with the wasm
launcher, the --experimental-options
option has to be provided.
When using a Context
, the method allowExperimentalOptions(true) has to be called on the Context.Builder.
Stable Options #
The following stable options are provided:
-
--wasm.Builtins
: Exposes some of the GraalWasm-provided built-in modules. The syntax for the value is[<linkingName>:]<builtinModuleName>,[<linkingName>:]<builtinModuleName>,...
. The requested modules are comma-separated. Every module may optionally be prefixed with a colon-separated linking name. If a linking name is given, the module is exported under the given linking name. Otherwise, the module is exported under its built-in module name.The provided built-in modules are:
spectest
: A module of simple functions useful for writing test cases. This module implements the same interface as the spectest module of the WebAssembly reference interpreter. Using it enables the execution of the core WebAssembly specification tests.wasi_snapshot_preview1
: GraalWasm’s implementation of the WebAssembly System Interface Snapshot Preview 1. Covers most of the documented API, except socket and signal support.
-
--wasm.WasiMapDirs
: A list of pre-opened directories that should be accessible through the WebAssembly System Interface API. The syntax for the value is[<virtualDir>::]<hostDir>,[<virtualDir>::]<hostDir>,...
. The pre-opened directories are comma-separated. Every directory may optionally be prefixed with a double-colon-separated virtual path. Inside the WebAssembly module, the directory is available at the virtual path. If the virtual path is omitted, the pre-opened directory will be on the same path as on the host filesystem.This option must be set to allow modules that use WASI to access the filesystem. Access will be granted only to the contents of these pre-opened directories.
Experimental Options #
Note that these options are experimental and are not guaranteed to be maintained or supported in the future.
To use them, the --experimental-options
option is required, or experimental options have to be enabled on the Context
, see above.
The options below correspond to feature proposals that add new features to the WebAssembly standard.
The accepted values are true
for enabling a feature and false
for disabling a feature.
Features that have already been merged into the WebAssembly spec are enabled by default in GraalWasm.
Features that are not yet merged into the spec are disabled by default.
Users can override the defaults to experiment with upcoming features or opt out of standardized features.
-
--wasm.BulkMemoryAndRefTypes
: Enable support for the bulk memory operations feature and reference types feature, exposing instructions for efficient memory initialization and adding support for first-class opaque references. Defaults totrue
. -
--wasm.ExtendedConstExpressions
: Enable support for the extended constant expressions feature, adding limited support for arithmetic instructions inside constant expressions. Defaults tofalse
. -
--wasm.Memory64
: Enable support for the Memory64 feature, letting memories be larger than 4 GiB. Defaults tofalse
. -
--wasm.MultiMemory
: Enable support for the multiple memories feature, allowing modules to have multiple memories. Defaults tofalse
. -
--wasm.MultiValue
: Enable support for the multi-value feature, letting functions return multiple values. Defaults totrue
. -
--wasm.SaturatingFloatToInt
: Enable support for the non-trapping float-to-int conversions feature, adding float-to-int conversion instructions that saturate instead of failing with a trap. Defaults totrue
. -
--wasm.SignExtensionOps
: Enable support for the sign-extension operators feature, adding instructions for extending signed integer values. Defaults totrue
. -
--wasm.SIMD
: Enable support for the fixed-width SIMD feature, introducing a new value type,v128
, and associated instructions for SIMD arithmetic. Defaults totrue
. -
--wasm.Threads
: Enable support for the threading feature, letting WebAssembly modules use new instructions for atomic memory access. Defaults tofalse
.
Using the GraalWasm Launcher #
GraalWasm standalones provide the wasm
launcher, which you can use to execute programs compiled as WebAssembly binary modules.
wasm [OPTION...] [--entry-point=FN] FILE [ARG...]
-
[OPTION...]
The options consist of GraalWasm engine options, prefixed with
--wasm.
, for example--wasm.WasiMapDirs=preopened-dir
, and any other polyglot engine options. When using thewasm
launcher, the--wasm.Builtins=wasi_snapshot_preview1
option is set by default so that you can directly execute modules compiled against the WebAssembly System Interface Snapshot Preview 1.The available options are documented in Options. You can also get a full list of GraalWasm engine options by passing the
--help:wasm
option to thewasm
launcher. To include internal options, use--help:wasm:internal
. Note that those lists both include stable, supported options, and experimental options. -
[--entry-point=FN]
You can specify the
--entry-point
option to choose which exported function is to be used as the module’s entry point, for example--entry-point=my_custom_main_fn
. If the--entry-point
option is missing, GraalWasm will try to auto-detect the entry point. It will first look for an exported function named_start
and then for an exported function named_main
. The first such function found will be executed as the entry point by thewasm
launcher. -
FILE
This is the path to the binary module that will be executed.
-
[ARG...]
Program arguments that are accessible to the program through the WASI args_get and args_sizes_get functions.