Giter Site home page Giter Site logo

wasmerio / wasmer-java Goto Github PK

View Code? Open in Web Editor NEW
563.0 21.0 49.0 328 KB

☕ WebAssembly runtime for Java

Home Page: https://medium.com/wasmer/announcing-the-first-java-library-to-run-webassembly-wasmer-jni-89e319d2ac7c

License: MIT License

Java 54.03% Rust 38.61% WebAssembly 0.28% Makefile 7.08%
java webassembly wasm rust java-library jni wasmer

wasmer-java's Introduction


A complete and mature WebAssembly runtime for Java based on Wasmer.

Features:

  • Easy to use: The wasmer API mimics the standard WebAssembly API,
  • Fast: The Wasmer JNI executes the WebAssembly modules as fast as possible, close to native speed,
  • Safe: All calls to WebAssembly will be fast, but more importantly, completely safe and sandboxed.

Install

The Wasmer package is published in Bintray on the wasmer/wasmer-jni repository.

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

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

Note: It is also possible to download the Java JAR file from the Github releases page! If you need to produce a JAR for your own platform and architecture, see the Development Section to learn more.

Example

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 tests/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 `tests/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.
        Instance instance = new Instance(wasmBytes);

        // Calls an exported function, and returns an object array.
        Object[] results = instance.exports.getFunction("sum").apply(5, 37);

        System.out.println((Integer) results[0]); // 42

        // Drops an instance object pointer which is stored in Rust.
        instance.close();
    }
}

There is more examples in the examples/ directory. Run them with the Makefile, such as: make run-example EXAMPLE=Simple to run the SimpleExample example.

API of the wasmer library

The root namespace is org.wasmer.

The Instance class

The 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.getFunction("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();

Exports

All exports, like functions or memories, are accessible on the Instance.exports field, which is of kind Exports (a read-only wrapper around a map of kind Map<String, exports.Export>). The Exports.get method returns an object of type Export. To downcast it to an exported function or to an exported memory, you can use the respective getFunction or getMemory methods. The following sections describe each exports in details.

Exported functions

An exported function is a native Java closure (represented by the exports.Function class), 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.

Function sum = instance.exports.getFunction("sum");
Object[] results = sum.apply(1, 2);

System.out.println((Integer) results[0]); // 3

Exported memories

An exported memory is a regular Memory class.

Memory memory = instance.exports.getMemory("memory_1");

See the Memory class section for more information.

The Module class

The 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();

Serialization and deserialization

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.getFunction("sum").apply(1, 2);

System.out.println((Integer) results[0]); // 3

The Memory class

A 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 specifying its exported name.
Memory memory = instance.exports.getMemory("memory");

// Gets the pointer value as an integer.
int pointer = (Integer) instance.exports.getFunction("return_hello").apply()[0];

// Reads the data from the memory.
ByteBuffer memoryBuffer = memory.buffer();
byte[] stringBytes = new byte[13];
memoryBuffer.position(pointer);
memoryBuffer.get(stringBytes);

System.out.println(new String(stringBytes)); // Hello, World!

instance.close();

Memory grow

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);

Development

The Wasmer JNI 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:

  • amd64-darwin,
  • amd64-linux,
  • amd64-windows.

More architectures and more platforms will be added in a close future. If you need a specific one, feel free to ask!

If you want to build the extension you will need the following tools:

  • Gradle, a package management tool,
  • Rust, the Rust programming language,
  • Java, because it's a Java project ;-).
$ git clone https://github.com/wasmerio/wasmer-java/
$ cd wasmer-java

To build the entire project, run the following command:

$ make build

To build the JAR package:

$ make package

This will generate the file build/libs/wasmer-jni-$(architecture)-$(os)-0.3.0.jar.

Automatic dependencies per architecture and platform

It is possible to infer the archive appendix automatically, see how.

According the Gradle Jar API, the $(architecture)-$(os) part is called the archive prefix. To infer that appendix automatically to configure your dependencies, you can use the following inferWasmerJarAppendix function:

String inferWasmerJarAppendix() {
    def nativePlatform = new org.gradle.nativeplatform.platform.internal.DefaultNativePlatform("current")
    def arch = nativePlatform.architecture
    def os = nativePlatform.operatingSystem

    def arch_name

    switch (arch.getName()) {
        case ["x86_64", "x64", "x86-64"]:
            arch_name = "amd64"
            break;

        default:
            throw new RuntimeException("`wasmer-jni` has no pre-compiled archive for the architecture " + arch.getName())
    }

    def os_name

    if (os.isMacOsX()) {
        os_name = "darwin"
    } else if (os.isLinux()) {
        os_name = "linux"
    } else if (os.isWindows()) {
        os_name = "windows"
    } else {
        throw new RuntimeException("`wasmer-jni` has no pre-compiled archive for the platform " + os.getName())
    }

    return arch_name + "-" + os_name
}

Finally, you can configure your dependencies such as:

dependencies {
    implementation "org.wasmer:wasmer-jni-" + inferWasmerJarAppendix() + ":0.3.0"
}

Testing

Run the following command:

$ make test

Note: Testing automatically builds the project.

Documentation

Run the following command:

$ make javadoc

Then open build/docs/javadoc/index.html.

What is WebAssembly?

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 […].

License

The entire project is under the MIT License. Please read the LICENSE file.

wasmer-java's People

Contributors

aiya000 avatar azam avatar d0iasm avatar dakota-doordash avatar hywan avatar jcaesar avatar jubianchi avatar ptitseb avatar syrusakbary avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

wasmer-java's Issues

Instance not found; using Maven

Describe the bug

I use maven and not gradle so I built the jar as described in the readme, then I installed the jar using maven cli:

mvn install:install-file -Dfile=wasmer-jni-amd64-linux-0.2.0.jar -DgroupId=org.wasmer -DartifactId=wasmer -Dversion=0.2.0 -Dpackaging=jar

This puts it in my local maven repo. Then I added it as a dependency:

  <dependency>
      <groupId>org.wasmer</groupId>
      <artifactId>wasmer</artifactId>
      <version>0.2.0</version>
    </dependency>

But when I run my code using the example SimpleExample.java almost exactly I recieve the error:

Exception in thread "main" java.lang.NoClassDefFoundError: org/wasmer/Instance
    at com.clopen.Clopen.main(Clopen.java:15)
Caused by: java.lang.ClassNotFoundException: org.wasmer.Instance
    at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:351)

Pretty much it compiles, using the wasmer-jni-amd64-linux-0.2.0.jar as a dependency but cannot find the org.wasmer.Instance object.

Maybe a solution to this is to add the program to the maven repository. I cannot use gradle because this test example of using rust to compile to wasm to run in java will be incorporated into a much larger maven project.

feat: Implement a basic memory API

A basic memory API would allow to:

  • Fetch an exported memory,
  • Read the memory (as bytes/buffer, or through views, like i32, i64, f32, and f64, is it necessary? Don't think so),
  • Write the memory.

Expected-ish code:

Memory memory = instance.exports.memory;
// or, probably better considering the type system of Java:
Memory memory = instance.memory(0);

Memory would ideally extend java.nio.Buffer? Don't know. Or simpler code:

byte[] data = memory.read(offset, length);
memory.write(offset, length, data);

The first API should be simple to plug Wasmer's memory API to Java, and then we can iterate on a nicer API.

⚠️ Be super careful about endianness. WebAssembly values are read and written in little endian byte order.

Update?

Summary

Heya, are there any plans on updating this any time soon? Since it's been quite a while now aha.

Standarize exports

In the current api, the exports are separated depending their type:

// For accessing the memory
Memory memory = instance.memories.get("memory");

// For accessing the functions
instance.exports.get("add_one")

We should aim for an API similar to the following:

// For accessing the memory
Memory memory = instance.exports.getMemory("memory");

// For accessing the function
instance.exports.getFunction("add_one");

Or:

// For accessing the memory
Memory memory = instance.exports.get("memory").asMemory();

// For accessing the function
instance.exports.get("add_one").asFunction();

Is this still alive?

This project is still using an old version of wasmer, is this abandoned? I'm needing this for a project

Cannot convert String type into WebAssembly

Describe the bug

I have the following code in my Rust project:

#[no_mangle]
#[wasm_bindgen]
pub fn test(str: String) -> String {
    test_internal(json::parse(str.as_str()).unwrap()).into()
}

#[no_mangle]
pub fn test_internal(json_value: JsonValue) -> Message {
    let age: Result<u8, _> = json_value.find("age");
    Message::new(vec![format!("Age {}.", age.unwrap())])
}

I've generated the .wasm with wasm-pack build --release, and in the Java side I have:

// Reads the WebAssembly module as bytes.
byte[] wasmBytes = Files.readAllBytes(wasmFilePath.get());

// Instantiates the WebAssembly module.
Instance instance = new Instance(wasmBytes);

// Calls an exported function, and returns an object array.
ObjectMapper om = new ObjectMapper();
String s = om.writeValueAsString(myObject);

Object[] results = instance.exports.getFunction("test")
        .apply(s);

// Drops an instance object pointer which is stored in Rust.
instance.close();

return (String) results[0];

But when trying to run the code above, it fails with the following exception:

Failed to convert the argument 0nth of `test` into a WebAssembly value.

Doing a bit of investigation, I've found that String conversion is not implemented, only minimal primitive types are.

Steps to reproduce

  1. Create a Rust project with a function that takes a String
  2. Compile with wasm-pack build --release
  3. On the Java side, create a simple project to load the compiled Rust Wasm and calls the function with a String argument.
  4. Try to run the code

Expected behavior

Correctly convert from-to string between Rust Wasm and Java.

Actual behavior

Fails with an exception.

Kotlin: Getting UnsatisfiedLinkError: no wasmer_jni in java.library.path when creating Instance

I am getting following exception with simple example as shown in in this introduction post:

Exception in thread "main" java.lang.UnsatisfiedLinkError: no wasmer_jni in java.library.path
	at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1860)
	at java.lang.Runtime.loadLibrary0(Runtime.java:870)
	at java.lang.System.loadLibrary(System.java:1124)
	at org.wasmer.Instance.<clinit>(Instance.java:17)
	at ApplicationKt.main(Application.kt:13)

See following repository: https://github.com/onurhkb/wasm-test

Edit: Using latest version of Intellij

Run the .wasm file I compiled that make a problem. I want to know the author of this project compile the rust to .wasm file.

Summary

I use the code like the tutorial ,
#[no_mangle] pub extern fn sum(x: i32, y: i32) -> i32 { x + y }
and use: cargo build --target=wasm32-wasi to compile my rust code to .wasm file.
and I run the .wasm file like this wasmtime hello-rust2wasm.wasm, it can worked.
but when I call the .wasm file in Java it comes an error.
Exception in thread "main" java.lang.RuntimeException: Failed to instantiate the module: Error while importing "wasi_snapshot_preview1"."fd_write": unknown import. Expected Function(FunctionType { params: [I32, I32, I32, I32], results: [I32] })
but if I use the author's file simple.wasm show in README. it can work.

so I want to know how the author compiles the rust to wasm and where I can learn the method.

Additional details

Provide any additional details here.

why wasmer-jni not support wasi import function, if my compiled wasm include wasi import , then wasmer-jni 0.3.0 not support

Thanks for proposing a new feature!

Motivation

A clear and concise description of what the motivation for the new feature is, and what problem it is solving.

Proposed solution

A clear and concise description of the feature you would like to add, and how it solves the motivating problem.

Alternatives

A clear and concise description of any alternative solutions or features you've considered, and why you're proposed solution is better.

Additional context

Add any other context or screenshots about the feature request here.

Please add this package to the JCenter() repo on Bintray.

Please add the bintray project to the JCenter common repo.
https://jfrog.com/blog/increase-your-maven-packages-exposure-by-adding-it-to-jcenter/

Without this, we have to add a custom repo just for this project; which complicates transitive deps. I'd like to be able to build and ship projectes to JCenter which depend upon this project.

For those wondering how to get it to link, you need this repo at the moment:
"https://dl.bintray.com/wasmer/wasmer-jni"

Migrate to Maven Central for jar distribution, Jcenter and Bintray are being shut down by May 1 2021

Thanks for proposing a new feature!

Motivation

Existing jar distribution through jcenter bintray will be shutting down on May 1, 2021. This renders the current repository based distribution broken.

https://jfrog.com/blog/into-the-sunset-bintray-jcenter-gocenter-and-chartcenter/

Proposed solution

Migrate build artifacts to use maven central repository instead of jcenter bintray

Alternatives

Users can grab the github release artifacts and upload to local repositories themselves, but not centralized and a higher barrier to entry for some users.

Additional context

N/A

Error when instantiating WASM files built from C/C++

Summary

I've had no luck yet running a test wasmer-java project using .wasm files built from C/C++. The included examples with wasmer-java work fine, but anything that I've built either via emscripten or wasienv throws RuntimeExceptions with missing imports:

Additional details

a C program built using wasienv, the .wasm file runs fine when executed:
wasmer run example.wasm -- DataInput

But when testing in wasmer-java I get this error:
Exception in thread "main" java.lang.RuntimeException: Failed to instantiate the module: 9 link errors: (1 of 9) Import not found, namespace: wasi_unstable, name: fd_prestat_get (2 of 9) Import not found, namespace: wasi_unstable, name: fd_prestat_dir_name (3 of 9) Import not found, namespace: wasi_unstable, name: proc_exit (4 of 9) Import not found, namespace: wasi_unstable, name: fd_fdstat_get (5 of 9) Import not found, namespace: wasi_unstable, name: fd_close (6 of 9) Import not found, namespace: wasi_unstable, name: args_sizes_get (7 of 9) Import not found, namespace: wasi_unstable, name: args_get (8 of 9) Import not found, namespace: wasi_unstable, name: fd_seek (9 of 9) Import not found, namespace: wasi_unstable, name: fd_write at org.wasmer.Instance.nativeInstantiate(Native Method) at org.wasmer.Instance.<init>(Instance.java:45) at Example.main(simple.java:18)
Additionally, a C++ project built using emscripten via JS:
em++ hello.cpp fib.cpp -s STANDALONE_WASM -s ALLOW_MEMORY_GROWTH=0 -s EXPORTED_FUNCTIONS="[_new_fib, _next_val]" -Wl, --no-entry -o hello.js || exit 1

Runs fine in the browser with javascript but when tested in wasmer-java I get this error:
Exception in thread "main" java.lang.RuntimeException: Failed to instantiate the module: link error: Import not found, namespace: wasi_snapshot_preview1, name: proc_exit at org.wasmer.Instance.nativeInstantiate(Native Method) at org.wasmer.Instance.<init>(Instance.java:45) at Example.main(simple.java:18)
Is there an import step I'm missing? Or a build sequence I need to follow? I've based the java code on the examples and it breaks at the instantiation point,:
`Path wasmPath = Paths.get(new Example().getClass().getClassLoader().getResource("hello.wasm").getPath())

// Reads the WebAssembly module as bytes.
byte[] wasmBytes = Files.readAllBytes(wasmPath);

    // Instantiates the WebAssembly module.
    Instance instance = new Instance(wasmBytes);`

The wasmer-jni*.jar is in the classpath. I'm running this on Linux Ubuntu. Both emscripten and wasienv are the most recent versions as of this question's posting.

Thanks for any help, I'd love to use WASM and Java if possible.

wasmer-java 32bit

Thanks for providing this library!

I would need a windows 32 bit version. Is this available?
Otherwise feel free to tell me, how i have to configure the build.gradle file, to produce a 32bit version :)

Best regards!

Add aarch64-darwin platform

Thanks for proposing a new feature!

Motivation

Most Macs nowadays run on Apple Silicon, but you‘re currently only providing a JAR for Intel based Macs. Those run a bit slower because they have to be emulated by Rosetta.

Proposed solution

Add a binary for aarch64-darwin.

Alternatives

The current amd64-darwin package is an alternative, but it is slower than a native package.

JVM fails with core dump

Describe the bug

Invocation of a WASM binary triggers a segfault in the VM, crashing it. It seems that this occurs quite frequently on my laptop, but I'm seeing successful runs also.

An example of a failing run: https://scans.gradle.com/s/d7otkguc6enr6/console-log?anchor=73
Without any code change, this one passed: https://scans.gradle.com/s/cqx4p4rdmfdf2

Steps to reproduce

Pre-requisites: install cargo and cargo install wasm-gc.

  1. Clone https://github.com/melix/gradle-wasm-plugin
  2. git chechout jvm-crash
  3. Run ./gradlew functionalTest
  4. See error (or not)

Expected behavior

The JVM shouldn't crash.

Actual behavior

The JVM crashes more often than it should.

Additional context

This behavior was observed under Linux Mint 20.1. I have attached a core dump.

hs_err_pid1026074.log

The problem seems to occur during finalization. It's worth noting that you shouldn't rely on finalize in Java.

Seems that commenting out the instance.close() call on https://github.com/melix/gradle-wasm-plugin/blob/2ff26beb103c8049e7215084852d7dbbde889870/wasm-base-tasks/src/main/java/me/champeau/gradle/wasm/tasks/AbstractWasmTask.java#L49 fixes the pb.

feat: Implement a module caching API

A module caching API would rely on the serialize/deserialize API providing by wasmer-runtime-core.

Ideally, the Module class should implement Serializable. Let's see how far we can go with this.

The problem it solves is: Skipping module compilation time if already done.

Add support for WASM imports

Motivation

I was trying to use wasmer-java to create a sample Java application that would be able to import and execute an Open Policy Agent policy compiled to WASM. More details about Open Policy Agent can be found here: https://www.openpolicyagent.org/docs/latest/wasm/.

An Open Policy Agent compiled WASM has a couple of imports, here is an excerpt from a policy.wasm using WASM text format:

  (import "env" "memory" (memory $env.memory 2))
  (import "env" "opa_abort" (func $env.opa_abort (type $t3)))
  (import "env" "opa_builtin0" (func $env.opa_builtin0 (type $t1)))
  (import "env" "opa_builtin1" (func $env.opa_builtin1 (type $t0)))
  (import "env" "opa_builtin2" (func $env.opa_builtin2 (type $t5)))
  (import "env" "opa_builtin3" (func $env.opa_builtin3 (type $t6)))
  (import "env" "opa_builtin4" (func $env.opa_builtin4 (type $t7)))

When trying to load use a policy.wasm from a simple Java app like the one below:

public class Application {

  public static void main(String[] args) throws IOException {
    byte[] wasmBytes = Files.readAllBytes(Paths.get("policy.wasm"));
    Instance instance = new Instance(wasmBytes);

    System.out.println(instance);
  }
}

I get the following exception:

Exception in thread "main" java.lang.RuntimeException: Failed to instantiate the module: 7 link errors: (1 of 7) Import not found, namespace: env, name: opa_abort (2 of 7) Import not found, namespace: env, name: opa_builtin0 (3 of 7) Import not found, namespace: env, name: opa_builtin1 (4 of 7) Import not found, namespace: env, name: opa_builtin2 (5 of 7) Import not found, namespace: env, name: opa_builtin3 (6 of 7) Import not found, namespace: env, name: opa_builtin4 (7 of 7) Import not found, namespace: env, name: memory
	at org.wasmer.Instance.nativeInstantiate(Native Method)
	at org.wasmer.Instance.<init>(Instance.java:45)
	at com.adobe.target.gw.Application.main(Application.java:12)

Proposed solution

As far as I can tell by looking here https://github.com/wasmerio/wasmer-java/blob/master/src/instance.rs#L26, we always pass an empty imports value. It would be great if we could pass some kind of object to Instance.nativeInstantiate(...) that would allow us to populate the "imports" before passing to wasmer runtime.

In the browser when loading WASM we can pass an import object like WebAssembly.instantiate(bufferSource, importObject), so it would be nice to have something similar in wasmer-java.

Alternatives

Not sure if there are other alternatives

Additional context

None

feat: Implement an export API

Ideally, a Wasm exported function should behave as any Java function, so that writing the following code will be natural:

int result = instance.exports.sum(1, 2);

It means that Instance must expose a public exports attribute, populated by a collection of function pointer or callbacks calling Wasm exported functions.

no wasmer_jni in java.library.path on MacOS

Summary

I try to run a wasm jni program in InteliJ on macOS , but I didn't make a success .

Additional details

Exception in thread "main" java.lang.UnsatisfiedLinkError: no wasmer_jni in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1867)
at java.lang.Runtime.loadLibrary0(Runtime.java:870)
at java.lang.System.loadLibrary(System.java:1122)
at org.wasmer.Instance.(Instance.java:17)
at Main.main(Main.java:18)

feat: Implement a module API

A module API allows to:

  • validate,
  • instantiate

Wasm bytes. Something like:

Module module = new Module(bytes);
module.validate();
Instance instance = module.instantiate();

thread '<unnamed>' panicked at 'assertion failed: res.eax == 0'

I found a runtime error as follow:

thread '<unnamed>' panicked at 'assertion failed: res.eax == 0', /home/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/raw-cpuid-7.0.4/src/lib.rs:295:13
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Exception in thread "main" java.lang.RuntimeException: Any
    at org.wasmer.Instance.nativeInstantiate(Native Method)
    at org.wasmer.Instance.<init>(Instance.java:45)

I found this problem both on Windows 11 and Ubuntu 18.04, the JDK version is 1.8, is there anyone can help me to solve this problem?

Need support for AArch64 platform Android

Hi Team,

I am trying to use wasm in Android using wasmer-java, but it is asking for the libwasmer_jni.so to be in EM_AARCH64 instead of EM_X86_64. It would be good if you provide support to AArch64 platform.

Thanks

Writing into the import memory of a wasm module

Summary

Is it currently possible to access and write into the import memory of a wasm module?

Additional details

I would like to run a wasm module which exports a function that reads from the import memory (env.memory). Is this supported currently? If yes it would be good to see an example or a test.

Asynchronous SEGV when running in Flink job

Description

When using an instance created from a Flink job in docker, the taskmanagers (= things that execute the stream processing) die with a SEGV shortly after calling a wasm function.

Steps to reproduce

Requires a bit of setup, I've created a docker-compose based test case:
https://github.com/jcaesar/wasmer-in-flink-segv
You should be able to run it with

docker-compose -p asdf kill \
&& docker-compose -p asdf rm -vf \
&& docker-compose -p asdf up  --build --abort-on-container-exit

Actual behavior

taskmanager1_1  | *** Aborted
taskmanager1_1  | Register dump:
taskmanager1_1  | 
taskmanager1_1  |  RAX: 0000000000000000   RBX: 0000000000000006   RCX: 00007f86f91367bb
taskmanager1_1  |  RDX: 0000000000000000   RSI: 00007f8660967f10   RDI: 0000000000000002
taskmanager1_1  |  RBP: 00007f86609681e0   R8 : 0000000000000000   R9 : 00007f8660967f10
taskmanager1_1  |  R10: 0000000000000008   R11: 0000000000000246   R12: 00007f86609689b0
taskmanager1_1  |  R13: 00007f865005f070   R14: 000000000000000b   R15: 00007f85fc00e610
taskmanager1_1  |  RSP: 00007f8660967f10
taskmanager1_1  | 
taskmanager1_1  |  RIP: 00007f86f91367bb   EFLAGS: 00000246
taskmanager1_1  | 
taskmanager1_1  |  CS: 0033   FS: 0000   GS: 0000
taskmanager1_1  | 
taskmanager1_1  |  Trap: 0000000e   Error: 00000007   OldMask: 00000404   CR2: f94ffe80
taskmanager1_1  | 
taskmanager1_1  |  FPUCW: 0000037f   FPUSW: 00000000   TAG: 00000000
taskmanager1_1  |  RIP: 00000000   RDP: 00000000
taskmanager1_1  | 
taskmanager1_1  |  ST(0) 0000 0000000000000000   ST(1) 0000 0000000000000000
taskmanager1_1  |  ST(2) 0000 0000000000000000   ST(3) 0000 0000000000000000
taskmanager1_1  |  ST(4) 0000 0000000000000000   ST(5) 0000 0000000000000000
taskmanager1_1  |  ST(6) 0000 0000000000000000   ST(7) 0000 0000000000000000
taskmanager1_1  |  mxcsr: 1f80
taskmanager1_1  |  XMM0:  000000000000000000000000ffffffff XMM1:  000000000000000000000000ffffffff
taskmanager1_1  |  XMM2:  000000000000000000000000ffffffff XMM3:  000000000000000000000000ffffffff
taskmanager1_1  |  XMM4:  000000000000000000000000ffffffff XMM5:  000000000000000000000000ffffffff
taskmanager1_1  |  XMM6:  000000000000000000000000ffffffff XMM7:  000000000000000000000000ffffffff
taskmanager1_1  |  XMM8:  000000000000000000000000ffffffff XMM9:  000000000000000000000000ffffffff
taskmanager1_1  |  XMM10: 000000000000000000000000ffffffff XMM11: 000000000000000000000000ffffffff
taskmanager1_1  |  XMM12: 000000000000000000000000ffffffff XMM13: 000000000000000000000000ffffffff
taskmanager1_1  |  XMM14: 000000000000000000000000ffffffff XMM15: 000000000000000000000000ffffffff
taskmanager1_1  | 
taskmanager1_1  | Backtrace:
taskmanager1_1  | /lib/x86_64-linux-gnu/libc.so.6(gsignal+0x10b)[0x7f86f91367bb]
taskmanager1_1  | /lib/x86_64-linux-gnu/libc.so.6(abort+0x121)[0x7f86f9121535]
taskmanager1_1  | /tmp/wasmer_jni7073396356486144275.lib(+0x250f07)[0x7f85d6d3cf07]
taskmanager1_1  | /tmp/wasmer_jni7073396356486144275.lib(+0x24bb46)[0x7f85d6d37b46]
taskmanager1_1  | /tmp/wasmer_jni7073396356486144275.lib(+0x9fad0)[0x7f85d6b8bad0]
taskmanager1_1  | /tmp/wasmer_jni7073396356486144275.lib(+0x9f156)[0x7f85d6b8b156]
taskmanager1_1  | /lib/x86_64-linux-gnu/libpthread.so.0(+0x12730)[0x7f86f94ee730]
taskmanager1_1  | /usr/local/openjdk-8/lib/amd64/server/libjvm.so(+0x6647a0)[0x7f86f87f47a0]
taskmanager1_1  | /usr/local/openjdk-8/lib/amd64/server/libjvm.so(+0x665744)[0x7f86f87f5744]
taskmanager1_1  | /usr/local/openjdk-8/lib/amd64/server/libjvm.so(JVM_DoPrivileged+0x2c6)[0x7f86f8855e96]
taskmanager1_1  | [0x7f86e11d0af5]

failed for task ':buildRust'

Summary

I try to run a wasm jni program in InteliJ on macOS , but I didn't make a success .

It fails with :

Execution failed for task ':buildRust'.
> Process 'command 'make'' finished with non-zero exit value 2

debug options says this:

make: *** [build-rust-amd64-darwin] Error 1

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':buildRust'.
> Process 'command 'make'' finished with non-zero exit value 2

wasmer-java for Apple silicon

Currently there is no jar available for Apple Silicon (M1). It would be great to see Mac OS support for both Intel and Apple Silicon.

Exception when passing a callback as parameter

Describe the bug

Trying to call a WASM method passing a callback parameter fails with a RuntimeException.

Steps to reproduce

The following Rust code builds the WASM code passed to Instance:

#[no_mangle]
pub extern fn greet(print: extern fn(u8)) {
    print(42)
}

The following Java code fails when trying to call the greet method:

Instance instance = new Instance(wasm);
Consumer<Object> print = (Object o) -> System.out.println("Printed: " + ((Integer) o));
instance.exports.getFunction("greet").apply(print);
instance.close();

Actual behavior

When run, this fails with the following exception:

Exception in thread "main" java.lang.reflect.InvocationTargetException
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
	at org.springframework.boot.loader.Launcher.launch(Launcher.java:108)
	at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
	at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88)
Caused by: java.lang.RuntimeException: Failed to convert the argument 0nth of `greet` into a WebAssembly value.
	at org.wasmer.Instance.nativeCallExportedFunction(Native Method)
	at org.wasmer.Exports.lambda$null$0(Exports.java:85)
	at org.example.wasmhost.WasmHostApplication.main(WasmHostApplication.java:45)
	... 8 more

Additional context

My Java version is:

$ java -version
openjdk version "11.0.11" 2021-04-20
OpenJDK Runtime Environment (build 11.0.11+9-Ubuntu-0ubuntu2.18.04)
OpenJDK 64-Bit Server VM (build 11.0.11+9-Ubuntu-0ubuntu2.18.04, mixed mode, sharing)

feat: Instance Imports

We should be able to pass imports to when instantiating a WebAssembly module, so the wasm code can call the host java functions and use their results.

Segfaulting the JVM

Describe the bug

I am currently developing WASM tooling and I am using wasmer-java interactively from Clojure. Sometimes, after a while, the JVM suddenly segaults because of Wasmer:

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007fe1df8c4f91, pid=27960, tid=27980
#
# JRE version: OpenJDK Runtime Environment (Zulu11.39+15-CA) (11.0.7+10) (build 11.0.7+10-LTS)
# Java VM: OpenJDK 64-Bit Server VM (11.0.7+10-LTS, mixed mode, tiered, compressed oops, g1 gc, linux-amd64)
# Problematic frame:
# C  [wasmer_jni2309101336629026624.lib+0x5ef91]  _$LT$hashbrown..raw..RawTable$LT$T$GT$$u20$as$u20$core..ops..drop..Drop$GT$::drop::hfb03333fcdd0f7eb+0x31
#
# Core dump will be written. Default location: Core dumps may be processed with "/usr/share/apport/apport %p %s %c %d %P %E" (or dumping to /home/adam/projects/clj/helins/wasmeta/core.27960)
#
# An error report file with more information is saved as:
# /home/adam/projects/clj/helins/wasmeta/hs_err_pid27960.log
[thread 28012 also had an error]
#
# If you would like to submit a bug report, please visit:
#   http://www.azulsystems.com/support/
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
rlwrap: warning: clojure crashed, killed by SIGABRT (core dumped).
rlwrap itself has not crashed, but for transparency,
it will now kill itself with the same signal

And here is the full report: https://gist.github.com/helins-io/ffbb4e46eaf5b4adbfc960952ac577e9

Steps to reproduce

In an interactive session (using a Clojure REPL), I often load a WASM file, create an instance, execute a function and close that instance right away. At first nothing happens. However, after a while, I get this SIGSEV.

Additional context

"After a while" propably means when GC kicks in. I guess this could be a double free error where finalizing the instance object tries to free pointer(s) which were already freed manually when closing the instance myself. Sounds plausible after skimming at the report.

Bump up WASI version to enable "wasi-snapshot-preview1"."proc_exit"

Motivation

I compiled a C library to wasm which contains the following import (in the .wat file)
(import "wasi-snapshot-preview1" "proc_exit" (func (;0;) (type 4)))

However, when I later use this module with java-wasmer I get the following errors:

Exception in thread "main" java.lang.RuntimeException: Failed to instantiate the module: Error while importing "wasi-snapshot-preview1"."proc_exit": unknown import. Expected Function(FunctionType { params: [I32], results: [] }).

Currently, from Cargo.toml it appears that wasmer-java is using an older version of WASI and I tried to compile wasmer-java with the updated packages:

 11 [dependencies]
 12 wasmer = { git = "https://github.com/wasmerio/wasmer", rev = "2.0.0" }
 13 wasmer-runtime = { git = "https://github.com/wasmerio/wasmer", rev = "1.0.0" }
 14 wasmer-runtime-core = { git = "https://github.com/wasmerio/wasmer", rev = "1.0.0" }

but make fails. Is there an easy way to bump up the versions?

Proposed solution

Update the WASI package versions to allow accessing the undefined WASI functions.

Alternatives

There aren't any.

Additional context

Nothing here as well. It's package versioning.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.