Run Java VM with WebAssembly

Let's touch WebAssembly, which is getting better recently. I would like to create an environment where Java can be executed as a subject. Yes, it's a Java interpreter (Java VM) that runs in a browser, like a Java applet.

First of all, I would like to decline. Although it is a Java interpreter that interprets Java bytecode, it implements minimal bytecode. Also, since it implements only a few classes under java / lang, it is practically useless. Personally, I made it for studying the Java interpreter. I'm sorry for those who have expected.

We will proceed as follows.

I referred to "waba" as the C language source code of the Java interpreter. I learned a lot. Thank you very much.

wabasoft  http://wabasoft.com/

I used "emscripten" for the WebAssembly compiler.  https://emscripten.org/index.html

The following is the sequel. Running JavaVM with WebAssembly: Supplement

Install emscripten

I installed it in the WSL environment of Windows 10. So I use Python2.7, but it was already installed.

> python --version
Python 2.7.15rc1
> git clone https://github.com/juj/emsdk.git
> cd emsdk
> ./emsdk install latest
> ./emsdk activate latest

You have now installed the WebAssembly compiler "emcc". When using it, you need to pass it through, so do the following:

> source ./emsdk_env.sh --build=Release

Creating a project folder

Create an appropriate folder and work.

Place a set of C language source files in the same folder.

I have posted it on the following GitHub.

https://github.com/poruruba/javaemu

> git clone https://github.com/poruruba/javaemu.git
> cd javaemu

Compile Java source code to embed in WebAssembly

Compile the Java source code. Java source code is divided into two types, and the placement method is changed. The first is Java source that is embedded in WebAssembly, and the other is Java source that is not embedded in WebAssembly. The latter is regular user-written Java source code. On the other hand, java / lang etc. are used by normal users, and the Java source of the system that does not change is the former. In addition, Java classes that have native functions that can be processed only in C language and that work with the interpreter are also the former.

It is assumed that the source code will be created under the java_src folder. Create a folder to put the compiled class files. Let's say pre_classes.

> mkdir pre_classes

The compilation is as follows.

>javac -encoding UTF8 -d pre_classes -sourcepath java_src java_src/base/framework/*.java java_src/java/lang/*.java java_src/test/*.java

The Java source files under base / framework and java / lang are the Java source of the system. java_src / test / *. java will be used for testing later, so please remove it after testing. Now you have a Java class file under the pre_classes folder.

I used the Oracle JDK on Windows. In the case of OpenJDK, I batted it with the class file on the execution environment, and I didn't know how to exclude it. .. ..

Compile C source code

Now let's compile

> emcc *.c -s WASM=1 -o javaemu.js -s "EXTRA_EXPORTED_RUNTIME_METHODS=['ccall', 'UTF8ArrayToString', 'stringToUTF8Array']" --preload-file pre_classes

(Reference) Compile-time options  https://emscripten.org/docs/tools_reference/emcc.html#emccdoc

-s WASM = 1 is a spell that indicates that a WASM file will be generated.

-o javaemu.js is for generating a file (javaemu.data) that combines WASM files (javaemu.wasm), utility Javascript (javaemu.js), and Java class files to be embedded in WebAssembly. The name javaemu is appropriate. Please use any name you like.

-s EXTRA_EXPORTED_RUNTIME_METHODS is the name of the function provided by javaemu.js that is allowed to be called from Javascript of the HTML page placed on the Web. ccall is required, but the other two are useful, so I set them.

--preload-file specifies the name of the folder where the files to be embedded in WebAssembly are located. The files under the specified folder name are grouped into a file called javaemu.data.

Of the completed files, the ones that will be placed on the Web are "javaemu.wasm", "javaemu.js", and "javaemu.data". javaemu.wasm is just a WebAssembly file compiled from C language.

Functions called from Javascript on web pages are defined in main.c.

main.c


int EMSCRIPTEN_KEEPALIVE setInoutBuffer(const unsigned char *buffer, long bufferSize );
int EMSCRIPTEN_KEEPALIVE setRomImage(unsigned char *romImage, long romSize );
int EMSCRIPTEN_KEEPALIVE callStaticMain(char *className, char *param );

Check the operation of Java bytecode placed on the Web and embedded in WebAssembly.

Upload the html of the files dropped from GitHub to the web server. We have also prepared a page for checking the operation. Place the three files you just generated in the html folder as well.

> cp javaemu.wasm javaemu.js javaemu.data html/

Or

> cd html
> ln -s ../javaemu.wasm ../javaemu.js ../javaemu.data .
> cd ..

(Please put it in the root folder of HTML, otherwise javaemu.js will not read the wasm and data files well)

Thankfully, emscripten has a simple web server feature, so I'll use that. The port number is 8080.

emrun --serve_root html --no_browser --port 8080 .

Now, let's access it from a browser. As a browser, I tried running it on Chrome on Windows.

http://localhost:8080

image.png

For clarity, I'm pressing F12 to bring up the developer console.

Around Class Name, enter the embedded Java class name for testing. It is "test / TestFunc".

The original source code looks like the following.

TestFunc.java


package test;

import base.framework.System;
import base.framework.Convert;
import base.framework.Util;

public class TestFunc{
  public static void main( String[] args ){
  	try
  	{
  		System.println("Hello test/TestFunc");

  		if( args.length >= 1 )
  			System.println("args[0]=" + args[0]);
  		
  		String[] input = System.getInput(-1);
  		for( int i = 0 ; i < input.length ; i++ )
	  		System.println("params[" + i + "]=" + input[i]);

  		System.setOutput(new String[]{ "World", "Good evening" });
  	}catch( Exception ex )
  	{
		System.print( ex.toString() );
  		ex.printStackTrace();
  	}
  }
}

Enter an appropriate character string in Input Arg and Input Params. Immediately press the "start was m" button.

Call the function implemented in C language with the following feeling. It takes a lot of work to load and run the WebAssembly file, but javaemu.js does it well.

start.js


            this.output_return = Module.ccall('callStaticMain', // name of C function 
                                    "number", // return type
                                    ["string", "string"], // argument types
                                    [this.class_name, this.input_arg]); // arguments

image.png

Then, while the messy debug characters were displayed in the console of the browser, I think that the following character string was displayed. The Java class file has been executed by the Java interpreter.

Hello test/TestFunc args[0]=ABCD params [] = Aiueo params [1] = Kakikukeko

Also, you should see the following on the page.

Output Return 0 Output Params ["World", "Good evening"]

Compile Java source code that was not embedded in WebAssembly.

Now let's create and run various Java sources.

I will create it under java_src. This time, we will create it under the test2 folder.

The compilation is as follows.

> mkdir classes
> javac -encoding UTF8 -d classes -sourcepath java_src -classpath pre_classes java_src/test2/*.java

I am creating a folder classes for storing class files. Since pre_classes is assumed to be embedded in the WebAssembly file, it is assumed that it is an existing class file and compiled.

Next, make the created class file a Jar file.

> jar cvf classes.jar -C classes .

The files under the classes folder are now grouped in the classes.jar file. Files other than the test2 class file have also been created, but they are harmless and can be ignored or excluded from the Jar file target.

Click the "Select File" button and specify the "classes.jar" created earlier. Below that, you'll see a list of the class files contained in the Jar file.

I used unzip.min.js of zlib.js to extract the Jar file, that is, the ZIP file.

zlib.js  https://github.com/imaya/zlib.js

Now run it again from your browser.

image.png

Specify test2 / TestFunc included in the Jar file for Class Name, and click the "start was m" button to execute.

Did you see something like this on the console? It becomes test2 / TestFunc and you can see that the corresponding source is running.

Hello test2/TestFunc args[0]=ABCD [] = Aiueo [1] = Kakikukeko

Supplement

The Java interpreter has been heavily customized from waba and is full of bugs, so I'll decline that much. .. ..

The explanation will be in the next article. First up to here.

The following is the sequel. Running JavaVM with WebAssembly: Supplement

that's all.

Recommended Posts

Run Java VM with WebAssembly
Running Java VM with WebAssembly: Supplement
Run batch with docker-compose with Java batch
Run an application made with Java8 with Java6
Profiling with Java Visual VM ~ Basic usage ~
Java development with Codenvy: Hello World! Run
Run Rust from Java with JNA (Java Native Access)
Using Gradle with VS Code, build Java → run
Get along with Java containers in Cloud Run
Install java with Homebrew
Change seats with java
Install Java with Ansible
Run Pico with docker
Run PostgreSQL on Java
Comfortable download with JAVA
Switch java with direnv
Run Payara with Docker
Download Java with Ansible
Let's scrape with Java! !!
Build Java with Wercker
Endian conversion with JAVA
[Tutorial] Download Eclipse → Run the application with Java (Pleiades)
[Tutorial] Download Eclipse → Run Web application with Java (Pleiades)
Serverless Java EE starting with Quarkus and Cloud Run
Easy BDD with (Java) Spectrum?
Use Lambda Layers with Java
Java multi-project creation with Gradle
Getting Started with Java Collection
Java Config with Spring MVC
Basic Authentication with Java 11 HttpClient
Let's experiment with Java inlining
[Template] MySQL connection with Java
Rewrite Java try-catch with Optional
[Java] JSON communication with jackson
Run TAO Core with Docker
Java to play with Function
Try DB connection with Java
Enable Java EE with NetBeans 9
[Java] JavaConfig with Static InnerClass
Try gRPC with Java, Maven
Let's operate Excel with Java! !!
Version control Java with SDKMAN
Run LIFF with Spring Boot
RSA encryption / decryption with java 8
Paging PDF with Java + PDFBox.jar
Sort strings functionally with java
Object-oriented (java) with Strike Gundam
Run Rails whenever with docker
[Java] Content acquisition with HttpCliient
Java version control with jenv
Troubleshooting with Java Flight Recorder
Streamline Java testing with Spock
Run java applet on ubuntu
Connect to MySQL 8 with Java
Error when playing with java
Using Mapper with Java (Spring)
Java study memo 2 with Progate
Getting Started with Java Basics
Seasonal display with Java switch
Use SpatiaLite with Java / JDBC
Study Java with Progate Note 1