Do you know GraalVM? It’s polygot runtime for JVM. I’m very interested in GraalVM. So today I set up it and run examples.
Officially Graal is explained as below:
GraalVM - New JIT Compiler and Polyglot Runtime for the JVM
Graal is a new just-in-time compiler for the JVM focused on peak performance and multi-language support. Graal offers performance advantages not only to Java code, but also to scripting languages such as JavaScript, Ruby, and R. Additionally, it enables the execution of native code on the JVM via an LLVM-based front end (project Sulong). Languages are executed by Graal via the Truffle framework, which comes with seamless interoperability and polyglot debugging and profiling functionality. Oracle Labs GraalVM: Programming Languages and Runtimes Overview
It’s a little confusing, Graal is not same as GraalVM. Simply stated, GraalVM consists of Graal and Truffle.
Set up
You can download GraalVM from the following URL. Oracle Labs GraalVM: Download
Then you uncompress the file in a directory of your choice and add “[GraalVM]/bin” to PATH. Finally try to run the following command.
$ graalvm -version Option -version is deprecated use --version GraalVM version: 0.23 Graal languages: JS: 0.9 R: 0.1 Ruby: 2.3.3 Java version: java version "1.8.0_121" Java(TM) SE Runtime Environment (build 1.8.0_121-b13) Java HotSpot(TM) 64-Bit Server VM (build 25.71-b01-internal-jvmci-0.26, mixed mode)
Shell
GraalVM has a shell mode and we can switch language in it.
$ graalvm --shell GraalVM MultiLanguage Shell 0.23 Copyright (c) 2013-7, Oracle and/or its affiliates JS version 0.9 R version 0.1 Ruby version 2.3.3 Usage: Use Ctrl+L to switch language and Ctrl+D to exit. Enter -usage to get a list of available commands. Ruby> 1 + 2 3
Run examples
GraalVM provides many examples in “[GraalVM]/bin” directory. So I try to run some of them.
Run multiple language code in Java code
import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.vm.PolyglotEngine; public class HelloPolyglotWorld { public static void main(String[] args) throws Exception { System.out.println("Hello polyglot world Java!"); PolyglotEngine engine = PolyglotEngine.newBuilder().build(); engine.eval(Source.newBuilder("print('Hello polyglot world JavaScript!');").mimeType("application/javascript").name("").build()).get(); engine.eval(Source.newBuilder("puts 'Hello polyglot world Ruby!'").mimeType("application/x-ruby").name("").build()).get(); engine.eval(Source.newBuilder("print('Hello polyglot world R!');").mimeType("application/x-r").name("").build()).get(); } }
We can use PolyglotEngine and Source class to run multiple language code in Java code. In this code I wrote Ruby, JavaScript and R code. The result is below.
$ javac -cp [path]/graalvm-0.23/lib/truffle/truffle-api.jar HelloPolyglotWorld.java $ graalvm HelloPolyglotWorld Hello polyglot world Java! Hello polyglot world JavaScript! Hello polyglot world Ruby! [1] "Hello polyglot world R!"
Ahead-of-Time Compilation with GraalVM
What ahead-of-Time Compilation means is following:
ahead-of-time (AOT) compilation is the act of compiling a higher-level programming language such as C or C++, or an intermediate representation such as Java bytecode or .NET Framework Common Intermediate Language (CIL) code, into a native (system-dependent) machine code so that the resulting binary file can execute natively.
https://en.wikipedia.org/wiki/Ahead-of-time_compilation
GraalVM ahead-of-time (AOT) compilation supports most of the Java code. Features that are not supported are: complex reflection, JNI calls, and dynamic class loading.
public class HelloAOTWorld { public static void main(String[] args) { System.out.println("Hello AOT world!"); } }
This is typical hello world example. We compile it with ordinal javac.
$ javac HelloAOTWorld.java $ ls HelloAOTWorld.class HelloAOTWorld.java README.md
To build a Image we run aop-image command. This command requires the name of the executable and the path to the main class.
$ aot-image -cp . -H:Name=hello-aot-world -H:Class=HelloAOTWorld Building image ... classlist: 3,480.44 ms (cap): 2,136.63 ms setup: 3,101.83 ms (typeflow): 4,000.54 ms (objects): 956.22 ms (features): 2.89 ms analysis: 5,136.17 ms universe: 394.75 ms (parse): 1,071.17 ms (inline): 1,543.93 ms (compile): 12,391.45 ms compile: 15,248.24 ms image: 1,065.07 ms debuginfo: 845.91 ms write: 1,397.95 ms [total]: 30,748.55 ms $ ls -lath total 10496 drwxr-xr-x@ 6 jyukutyo staff 204B 5 26 13:45 . -rwxr-xr-x 1 jyukutyo staff 5.1M 5 26 13:45 hello-aot-world -rw-r--r-- 1 jyukutyo staff 436B 5 26 13:42 HelloAOTWorld.class drwxr-xr-x@ 10 jyukutyo staff 340B 5 24 17:13 .. -rw-r--r--@ 1 jyukutyo staff 133B 5 20 03:33 HelloAOTWorld.java -rw-r--r--@ 1 jyukutyo staff 2.1K 5 20 03:33 README.md
File hello-aot-world was created and its size is 5.1M(!). You can invoke the executable as follows:
$ ./hello-aot-world Hello AOT world!
Did it!