Jul 1, 2024
Jul 1, 2024
N/A Views
MD

Warning

This article was automatically translated by OpenAI (gpt-4o).It may be edited eventually, but please be aware that it may contain incorrect information at this time.

In the previous article, we executed wasm on Java using Chicory. The same can be done with GraalVM (GraalWasm).

Let's redo the content of the previous article using GraalWasm.

By adding the following dependency libraries, you can load and execute wasm on a Java application.

    <dependency>
        <groupId>org.graalvm.polyglot</groupId>
        <artifactId>polyglot</artifactId>
        <version>24.0.1</version>
    </dependency>
    <dependency>
        <groupId>org.graalvm.polyglot</groupId>
        <artifactId>wasm-community</artifactId>
        <version>24.0.1</version>
        <type>pom</type>
    </dependency>

Let's create a sample wasm file from a WAT file. Create the following file SumSquared.wat.

It takes two i32 parameters, adds them, and returns the squared value.

(module
  (func (export "SumSquared")
    (param $value_1 i32) (param $value_2 i32)
    (result i32)
    (local $sum i32)

    (i32.add (local.get $value_1) (local.get $value_2))
    local.set $sum
    (i32.mul (local.get $sum) (local.get $sum))
  )
)

Tip

I used the sample code from Introduction to WebAssembly.

Introduction to WebAssembly

Convert it to wasm using wat2wasm.

wat2wasm SumSquared.wat 

SumSquared.wasm will be generated. Load and execute this wasm in Java.

package org.example;

import java.io.IOException;
import java.net.URL;
import java.util.Objects;

import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.Source;
import org.graalvm.polyglot.Value;

public class Main {
    public static void main(String[] args) throws IOException {
        try (Context context = Context.newBuilder().allowAllAccess(true).build()) {
            context.initialize("wasm");
            URL resource = Main.class.getClassLoader().getResource("SumSquared.wasm");
            Source source = Source.newBuilder("wasm", Objects.requireNonNull(resource)).name("main").build();
            context.eval(source);
            Value sumSquared = context.getBindings("wasm").getMember("main").getMember("SumSquared");
            Value result = sumSquared.execute(2, 3);
            System.out.println("Result: " + result.asInt()); // should print "Result: 25" (= (2 + 3)^2)
        }
    }
}

Run the Java application.

$ mvn -q compile exec:java -Dexec.mainClass=org.example.Main
Result: 25

This application will work even if the runtime is not GraalVM. For differences in optimization, refer to this document.

If the runtime is not GraalVM, the following WARN log will be output.

[To redirect Truffle log output to a file use one of the following options:
* '--log.file=<path>' if the option is passed using a guest language launcher.
* '-Dpolyglot.log.file=<path>' if the option is passed using the host Java launcher.
* Configure logging using the polyglot embedding API.]
[engine] WARNING: The polyglot engine uses a fallback runtime that does not support runtime compilation to native code.
Execution without runtime compilation will negatively impact the guest application performance.
The following cause was found: JVMCI is not enabled for this JVM. Enable JVMCI using -XX:+EnableJVMCI.
For more information see: https://www.graalvm.org/latest/reference-manual/embed-languages/#runtime-optimization-support.
To disable this warning use the '--engine.WarnInterpreterOnly=false' option or the '-Dpolyglot.engine.WarnInterpreterOnly=false' system property.

You can suppress the log by adding the following JVM options.

MAVEN_OPTS="-XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Dpolyglot.engine.WarnInterpreterOnly=false" mvn -q compile exec:java -Dexec.mainClass=org.example.Main

The full source code is here.

I would like to compare the performance of Chicory, GraalWasm, and wasmtime-java.

Found a mistake? Update the entry.
Share this article: