wasmerio / wasmer-java

☕ WebAssembly runtime for Java

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

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

feat: Instance Imports

syrusakbary opened this issue · comments

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.

This is resolved in master. Closing the issue

(got confused about exports, reopening)

+1 would be super useful!

Agree! Is there any workaround?

We are working on a small refactor that will enable this very easily.

Any updates?

The refactor is now publicly available (wasmer 1.0.0-alpha). We just need to update the bindings :)

@syrusakbary Can I call the host java functions and use their results from wasm code now? If so, could you tell me how to do? Thanks!

Host functions aren't supported yet. We are going to work on it :-).

Will host funtions be supported in 2021?

In 2021 for sure! I hope in a couple of weeks :-).

@Hywan is this being worked on? We're particularly interested in using it for memory import

I had a bit of a go at implementing: https://github.com/jcaesar/wasmer-java/compare/wasmer-2...jcaesar:imports?expand=1
I can't test it because gradle, so I don't expect it to work as is.

In all honesty, wasmer-java needs a rewrite, and one without the jni crate. That's an unwinnable game of catchup with glue code of dubious safety.

Any new info on this?

In 2021 for sure! I hope in a couple of weeks :-).

@Hywan Hello, now it's 2022.

Ivan quit working for wasmerio 4 months ago. ;)

oh dear :v
@jcaesar does this mean that this feature is frozen?

Well, don't ask me… but I assume it's way down the list. If someone implemented it and made a PR (well, or finished my code), I assume it would get merged and released. [Edit:] Well, who knows, it might not. The releases were on bintray after all. Nobody has taken care of that either.

@jcaesar I have finished your code and made a PR #64.

@beaclnd92 I do a windows build of your PR. It runs without any errors.
But if I run my java app I got the following exception:

Exception in thread "main" java.lang.UnsatisfiedLinkError: 'long org.wasmer.Imports.nativeImportsWasi()'
at org.wasmer.Imports.nativeImportsWasi(Native Method)
at org.wasmer.Imports.wasi(Imports.java:90)

I want to run the mappings.wasm from https://github.com/mozilla/source-map/blob/master/lib/mappings.wasm

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.apache.commons.io.IOUtils;
import org.wasmer.Exports;
import org.wasmer.Imports;
import org.wasmer.Imports.Spec;
import org.wasmer.Instance;
import org.wasmer.Module;
import org.wasmer.Native;

public class WASM
{
	public static void main(String[] args)
	{
		new WASM();
	}
	
	public class WASMMapping
	{
		public int generatedLine = 0;
		public int generatedColumn = 0;
		public Integer lastGeneratedColumn = null;
		public String source = null;
		public Integer originalLine = null;
		public Integer originalColumn = null;
		public String name = null;
	}

	public Exports exports;
	private Instance wasm;

	public WASM()
	{
		init();
	}

	private void init()
	{
		byte[] moduleBytes;
		try (InputStream is = this.getClass().getResourceAsStream("mappings.wasm");)
		{
			moduleBytes = IOUtils.toByteArray(is);
			String platform = Native.getCurrentPlatformIdentifier();
			System.out.println(platform);

			/** https://github.com/beaclnd92/wasmer-java/tree/imports/src/java/org/wasmer */
			if (Module.validate(moduleBytes))
			{
				Module m = new Module(moduleBytes);

				List<Spec> specImpList = new ArrayList<>();
				/** https://github.com/mozilla/source-map/blob/master/lib/wasm.js */
				Spec spec = new Spec("env", "mapping_callback", new java.util.function.Function<List<Number>, List<Number>>() {

					@Override
					public List<Number> apply(List<Number> t)
					{
						WASMMapping mapping = new WASMMapping();
						t.forEach(e -> System.out.println(e));

						return Collections.emptyList();
					}

				}, Collections.emptyList(), Collections.emptyList());
				specImpList.add(spec);

				Imports imp = Imports.from(specImpList, 0);
				this.wasm = m.instantiate(imp);
				this.exports = this.wasm.exports;
			}
		}
		catch (IOException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

When I use the code above I got a java runtime error:

windows-amd64
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ffc6bb1b1a3, pid=36420, tid=5736
#
# JRE version: OpenJDK Runtime Environment (11.0.6+10) (build 11.0.6+10-LTS)
# Java VM: OpenJDK 64-Bit Server VM (11.0.6+10-LTS, mixed mode, tiered, compressed oops, g1 gc, windows-amd64)
# Problematic frame:
# C  [wasmer_jni12599045650012626710.lib+0x1b1a3]
#
# No core dump will be written. Minidumps are not enabled by default on client versions of Windows
#

# An error report file with more information is saved as:
# D:\app\hs_err_pid36420.log
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.java.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#

hs_err_pid36420.log

Any help appreciated
Thanks

Think I have unterstand how to use it. ...

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.apache.commons.io.IOUtils;
import org.wasmer.Exports;
import org.wasmer.Imports;
import org.wasmer.Imports.Spec;
import org.wasmer.Instance;
import org.wasmer.Module;
import org.wasmer.Native;
import org.wasmer.Type;

public class WASM extends Module
{
	public static void main(String[] args)
	{
		new WASM();
	}

	static byte[] moduleBytes;

	static
	{
		try (InputStream is = WASM.class.getResourceAsStream("mappings.wasm");)
		{
			moduleBytes = IOUtils.toByteArray(is);
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}

	public class WASMMapping
	{
		public int generatedLine = 0;
		public int generatedColumn = 0;
		public Integer lastGeneratedColumn = null;
		public String source = null;
		public Integer originalLine = null;
		public Integer originalColumn = null;
		public String name = null;
	}

	public Exports exports;
	private Instance wasm;

	public WASM()
	{
		super(WASM.moduleBytes);
		init();
	}

	private void init()
	{
		String platform = Native.getCurrentPlatformIdentifier();
		System.out.println(platform);

		// https://github.com/beaclnd92/wasmer-java/tree/imports/src/java/org/wasmer
		if (Module.validate(moduleBytes))
		{
//				Module m = new Module(moduleBytes);
			List<Type> typeList = new ArrayList<>();
			for (int t = 0; t < 10; t++)
				typeList.add(Type.I32);

			List<Spec> specImpList = new ArrayList<>();
			// https://github.com/mozilla/source-map/blob/master/lib/wasm.js
			Spec spec = new Spec("env", "mapping_callback", new java.util.function.Function<List<Number>, List<Number>>() {

				@Override
				public List<Number> apply(List<Number> t)
				{
					WASMMapping mapping = new WASMMapping();
					t.forEach(e -> System.out.println(e));

//						// JS uses 1-based line numbers, wasm uses 0-based.
//						mapping.generatedLine = generatedLine + 1;
//						mapping.generatedColumn = generatedColumn;
//
//						if (hasLastGeneratedColumn)
//						{
//							// JS uses inclusive last generated column, wasm uses exclusive.
//							mapping.lastGeneratedColumn = lastGeneratedColumn - 1;
//						}
//
//						if (hasOriginal)
//						{
//							mapping.source = source;
//							// JS uses 1-based line numbers, wasm uses 0-based.
//							mapping.originalLine = originalLine + 1;
//							mapping.originalColumn = originalColumn;
//
//							if (hasName)
//							{
//								mapping.name = name;
//							}
//						}

//			            callbackStack[callbackStack.length - 1](mapping);
//						// TODO Auto-generated method stub
					return Collections.emptyList();
				}

			}, typeList, Collections.emptyList());
			specImpList.add(spec);

			Imports imp = Imports.from(specImpList, this.modulePointer);
			this.wasm = this.instantiate(imp);
			this.exports = this.wasm.exports;
		}
//		}
//		catch (IOException e)
//		{
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
	}
}

@EXEC-CSM I just recognized it's inconvenient to use,so I have fixed the implementation. We can use it like below:

Module m = new Module(moduleBytes);
Imports imp = Imports.from(specImpList, m);
Instance i = m.instantiate(imp);

Hello, any update of this? Will Import support function be released with next version? @beaclnd92
Btw, is there anyone can teach me how to build @beaclnd92's PR on Mac locally, maybe I can play around with it :). Thanks.

Hi @i059917, while waiting for this to be merged I've been successfully able to develop using imports on beaclnd92's work on Mac, works really well. Seems as simple as cloning beaclnd92 repo and checking out the imports branch.

git clone https://github.com/beaclnd92/wasmer-java
cd wasmer-java
git checkout imports

make then creates you the wasmer-jni-amd64-darwin-0.3.0.jar you need (following same instructions as for wasmer-java build). I did find I needed to run using -Dos.arch=amd64 on the JVM for it to find the JNI bindings though.

I somehow doubt wasmer-java is still anywhere on wasmerio's priority list… Might be best if someone with vested interest (I no longer have) forked this and put it onto Maven Central, or so?

I somehow doubt wasmer-java is still anywhere on wasmerio's priority list

We are prioritizing a refactor of Wasmer at the moment, but meanwhile will welcome any contributions from the community.
Wasmer-Java as of right now has to be updated with the latest Wasmer API, as of now it's using the 0.x API.

This Wasmer JNI bindings were using the latest API afaik:
https://github.com/Salpadding/wasmer-jni

https://github.com/Salpadding/wasmer-jni

Neat, that even supports instance imports.