16 Oracle Graal Vm Introduction Standing at the Frosty Summit Alone, Overlooking Tiny Mountains

16 Oracle GraalVM Introduction- Standing at the Frosty Summit Alone, Overlooking Tiny Mountains #

Introduction and Features of GraalVM #

Through understanding various JVM-related technologies, we can see that the Java ecosystem is becoming increasingly complex and powerful. Looking around, over the past decade, there has been a constant stream of various technologies and platforms, each with their own use cases and user base. With the emergence and development of concepts such as microservices and cloud-native, more and more technologies are being integrated together. As the most popular platform technology, Java/JVM naturally cannot stay out of this trend. In this section, we introduce GraalVM, a comprehensive language platform:

  • In terms of breadth of functionality, its goal is to bridge different language platforms so that developers can benefit from the strengths of different platforms. Different teams and modules can use different platforms to work together. (This is also a popular trend in microservice architecture. Imagine a very large product line, where multiple teams maintain dozens of independently deployed and running service modules with different functionalities. Each team can choose the appropriate language and platform tools according to their own ideas. But as the business evolves, modules are constantly being refactored and reshuffled. How do we connect Python’s algorithm service and Node.js’s REST scaffolding with Java modules?!)
  • In terms of depth of performance, it can convert various programs into native applications, running without intermediate languages and virtual machines, thus achieving optimal performance, including running speed and memory usage.

What is GraalVM #

GraalVM is an open-source universal virtual machine product developed by Oracle. It is officially referred to as Universal GraalVM, and it is a new generation of universal multi-language high-performance virtual machine. It can execute various high-performance and interoperable tasks, allowing users to build multi-language applications without additional costs.

The official website is:

https://www.graalvm.org

What are the features of GraalVM? #

GraalVM can run independently or be used in different deployment scenarios, such as OpenJDK virtual machine environments, Node.js environments, or Oracle and MySQL database environments. The following diagram from the GraalVM official website shows the currently supported platform technologies.

GraalVM system diagram

GraalVM supports a wide range of languages, including:

  • JVM-based languages (such as Java, Scala, Groovy, Kotlin, Clojure, etc.);
  • LLVM-based languages (such as C, C++, etc.);
  • Dynamic languages, such as JavaScript, Ruby, Python, and R.

It includes the following dynamic language engines:

  • JavaScript engine: Graal.js is a JavaScript interpreter/compiler that can run Node.js applications on the JVM.
  • FastR engine: This is an interpreter/compiler for the R language.
  • RubyTruffle engine: It supports Ruby and performs better than Ruby.

What features does GraalVM support?

  • Higher compilation quality and execution performance. Whether it is Java, Ruby, or R, the code compiled by GraalVM’s compiler has better performance.
  • Combining JavaScript, Java, Ruby, and R in development.
  • Running native languages on GraalVM.
  • Developing universal tools for all programming languages.
  • Extending JVM-based applications.
  • Extending native applications.
  • Compiling Java programs into native libraries for linking and calling by other programs.
  • Supporting multiple languages in database environments, mainly Oracle and MySQL database environments.
  • With GraalVM as a base, we can even create our own language.
  • For Node.js developers, GraalVM environment supports larger heap memory and has minimal performance loss.
  • Shorter program startup time.
  • Lower memory usage.

Startup time comparison:

microservices Memory Usage Comparison:

microservices

Pain Points Resolved #

GraalVM provides a comprehensive ecosystem that eliminates the isolation between programming languages, bridging the gap between different languages, and achieving interoperability in a shared runtime, enabling us to perform mixed-language programming.

Languages executed with Graal can invoke each other and allow the use of libraries from other languages, providing language interoperability. It also incorporates the latest research in compiler technology, resulting in much better performance than traditional JVM in high-load scenarios.

GraalVM’s mixed-language programming can address common issues in development, such as:

  • I need a library that my language doesn’t have, so I have to write my own;
  • The language that is best suited to solve my problem cannot be executed in my environment;
  • My language has solved this problem, but it runs too slow;
  • Through the use of the Polyglot API, GraalVM aims to provide developers with true language-level freedom.

By allowing developers to use their preferred languages, productivity can be improved, and there is a greater chance of winning market share.

How Cross-Language Works #

GraalVM provides a seamless value passing mechanism between different languages without the need for serialization and deserialization, ensuring zero-overhead interoperation across languages, which means no performance loss, hence its claim as a high-performance virtual machine.

GraalVM has developed a “Cross-Language Interoperability Protocol,” a special interface protocol that each language running on GraalVM must implement to ensure cross-language interoperability. Languages can efficiently pass values without the need to understand each other. This protocol is continuously being improved and will support more features in the future.

Weakening the Concept of a Main Language

GraalVM has developed an experimental launcher called Polyglot. In Polyglot, the concept of a main language does not exist, and each language is treated equally. Polyglot allows running programs written in any language without the need for separate launchers for each language. Polyglot automatically categorizes languages based on file extensions.

Shell

GraalVM also developed a dynamic language Shell, which by default uses the JS language and can switch to any other language for interpretation.

Compiling Java Programs into Executable Files #

As we know, after the introduction of Hotspot, it was claimed to achieve 80% of C++ performance, with the key being Just-In-Time (JIT) compilation.

It can be speculated that high performance lies in compilation rather than interpreted execution.

Similarly, if Java code can be compiled into native machine code, performance will undoubtedly be greatly improved.

Fortunately, GraalVM has static compilation capabilities and can compile Java programs into native executable binaries.

GraalVM can generate native images for JVM-based programs. During image generation, it performs ahead-of-time (AOT) full compilation by using static analysis techniques, starting from the Java main method and finding all reachable code. The resulting binary executable file contains all the machine code instructions for the entire program, enabling quick startup and execution, as well as being linkable by other programs.

During compilation, the GraalVM compiler can also be included to provide additional Just-In-Time (JIT) compilation support, enabling high-performance execution of any GraalVM-based language.

To achieve additional performance, boot optimizations collected from the previous run of an application can be used to build a native image. An example of how to build a native image can be seen later in this document.

When running an application in the JVM, there is an initial startup process that consumes time and occupies additional memory. However, a statically compiled program occupies less memory and starts faster relative to interpreted execution.

GraalVM Components #

GraalVM consists of core components and additional components bundled together for download. The current latest version of GraalVM is 19.3.1, which is a standalone deployment of JDK. It also includes a shared runtime for executing Java or JVM-based languages (such as Scala, Kotlin), dynamic languages (such as JavaScript, R, Ruby, Python), and LLVM-based languages (such as C, C++).

  • Runtimes: primarily Java Runtime System and NodeJS Runtime System
  • Libraries: e.g., compilers, JavaScript interpreter, LLVM bytecode executer, Polyglot API, etc.
  • Tools: JavaScript REPL environment, command-line tools for LLVM, installation programs for supporting other languages.

Download and Installation #

GraalVM supports Docker containers, but this article will not cover it. For related information, please refer to:

https://hub.docker.com/r/oracle/graalvm-ce/

Now let’s see how to download and install GraalVM in the development environment.

  1. Open the official website:

https://www.graalvm.org/

  1. Find the download page:

https://www.graalvm.org/downloads/

From the download page, we can see that GraalVM is available in two versions: Community Edition and Enterprise Edition.

Community Edition

The Community Edition is the free version and offers versions based on OpenJDK 8 and OpenJDK 11. It supports 64-bit systems based on the x86 architecture, including macOS, Linux, and Windows platforms.

To download, go to GitHub. The download page is:

https://github.com/graalvm/graalvm-ce-builds/releases

Enterprise Edition

The Enterprise Edition provides versions based on Oracle Java 8 and Oracle Java 11. It mainly supports macOS and Linux systems. The GraalVM Enterprise Edition for Windows is still an experimental developer version.

Each license costs about 1000 to 1500 RMB. However, following Oracle’s practice, you can download and try it for free.

To download, go to OTN (Oracle TechNetwork):

https://www.oracle.com/technetwork/graalvm/downloads/index.html

Choose the appropriate version based on your needs. For example, let’s choose the Community Edition.

The components of the Community Edition include:

  • JVM
  • JavaScript Engine & Node.js Runtime
  • LLVM Engine
  • Developer Tools

From the GitHub download page, find the download link.

As shown in the following image:

70802368.png

Different download links are provided based on the operating system (macOS/darwin, Linux, Windows), CPU architecture (AArch64, AMD64 (Intel/AMD)), and JDK version. Choose the appropriate download link for your system.

For example, for macOS with JDK 11, the corresponding download files are:

# GraalVM main application installation package
graalvm-ce-java11-darwin-amd64-19.3.1.tar.gz
# Installation package for llvm-toolchain; use gu -L command
llvm-toolchain-installable-java11-darwin-amd64-19.3.1.jar
# Installation package for native-image tool; use gu -L command
native-image-installable-svm-java11-darwin-amd64-19.3.1.jar

For Windows, only a single zip package is provided:

# JDK 11 version
graalvm-ce-java11-windows-amd64-19.3.1.zip
# JDK 8 version
graalvm-ce-java8-windows-amd64-19.3.1.zip

Save the file by right-clicking and selecting “Save As”.

Since certain resources on GitHub may be blocked, some techniques may be required.

If you are unable to download, you can seek help from your peers or join our discussion group. Alternatively, you can try downloading the Enterprise Edition from Oracle or use a download manager like Thunder.

After completing the download, extract the files. You will find that it has the structure of a JDK.

Alright, for someone who knows how to use Java, this should be no problem.

Go to the bin directory after extraction and check the version:

# Note that this is the author's directory
cd graalvm-ce-java11-19.3.1/Contents/Home/bin/
# Check the Java version
./java -version

openjdk version "11.0.6" 2020-01-14
OpenJDK Runtime Environment GraalVM CE 19.3.1 (build 11.0.6+9-jvmci-19.3-b07)
OpenJDK 64-Bit Server VM GraalVM CE 19.3.1 (build 11.0.6+9-jvmci-19.3-b07, mixed mode, sharing)

It’s not much different from using the JDK, right?

If it’s an isolated environment, you can also set the PATH environment variable, etc.

In addition to the JDK-related executable files in the bin directory after extraction, there are also:

  • The js file, which can be used to start the JavaScript console, similar to the Chrome debugging console’s REPL environment. Press CTRL+C to exit.
  • The node file, which is the embedded Node.js that uses GraalVM’s JavaScript engine.
  • The lli file, which is the high-performance LLVM bitcode interpreter integrated into GraalVM, according to the official description.
  • The gu file, which stands for GraalVM Updater, is a program installation tool. For example, it can install language packs for Python, R, and Ruby.

Examples #

The official website provides GraalVM-related introductions and developer documentation for various programming languages:

Java Usage #

After downloading and unpacking, you only need to set the PATH correctly to use it for Java development.

Take a look at the official example code:

public class HelloWorld {
  public static void main(String[] args) {
    System.out.println("Hello, World!");
  }
}

Here, to save time, let’s do something stupid. Just understand the meaning, and you can experiment like me.

# Check the current directory
$ pwd
/Users/renfufei/SOFT_ALL/graalvm-ce-java11-19.3.1/Contents/Home/bin

# View the source file
$ cat HelloWorld.java
public class HelloWorld {
  public static void main(String[] args) {
    System.out.println("Hello, World!");
  }
}

Then compile and execute it:

# Check the current directory
$ pwd
/Users/renfufei/SOFT_ALL/graalvm-ce-java11-19.3.1/Contents/Home/bin

# Compile
$ ./javac HelloWorld.java

# Execute the program
$ ./java HelloWorld
Hello, World!

OK, the program outputs as expected.

For more examples, please refer to:

https://www.graalvm.org/docs/examples/

The official examples are interesting and help improve our development skills.

Usage of JS #

Run the JS REPL debugging environment:

$ ./js
> 1 + 1
2

To exit, press CTRL+C.

View the versions of node and npm:

$ ./node -v
v12.14.0

$ ./npm -v
6.13.4

You can now install various dependencies and develop and use them just like in a regular Node.js environment.

For more programs, please refer to:

https://www.graalvm.org/docs/getting-started/#running-javascript

Usage of LLVM #

According to the official example:

https://www.graalvm.org/docs/getting-started/#running-llvm-bitcode

We execute the following command to install LLVM-related tools:

$ ./gu install llvm-toolchain
Downloading: Component catalog from www.graalvm.org
Processing Component: LLVM.org toolchain
Downloading: Component llvm-toolchain: LLVM.org toolchain from github.com
[                    ]

If the download speed is slow, it will take a long time. There is no progress bar displayed here, so be patient.

If the installation fails due to network issues, you can also download and use the local jar file for installation:

./gu -L install ../lib/llvm-toolchain-installable-java11-darwin-amd64-19.3.1.jar

The -L option is equivalent to --local-file or --file, which means installing the component from a local file. Just make sure the path is correct.

After installing llvm-toolchain, view the installation path and add it to the environment variable:

$ ./lli --print-toolchain-path
/Users/renfufei/SOFT_ALL/graalvm-ce-java11-19.3.1/Contents/Home/languages/llvm/native/bin

$ export LLVM_TOOLCHAIN=$(./lli --print-toolchain-path)

$ echo $LLVM_TOOLCHAIN
/Users/renfufei/SOFT_ALL/graalvm-ce-java11-19.3.1/Contents/Home/languages/llvm/native/bin

Note that here I took a shortcut and did not configure the PATH, so I used ./lli.

Create a C program file with the following content:

cat hello.c

#include <stdio.h>
int main() {
    printf("Hello from GraalVM!\n");
    return 0;
}

Then you can compile and execute the bitcode:

# Compile
$ $LLVM_TOOLCHAIN/clang hello.c -o hello

# Execute
$  ./lli hello
Hello from GraalVM!

Installing other tools and language development environments #

Installing Ruby

Refer to the installation documentation:

https://www.graalvm.org/docs/getting-started/#running-ruby

./gu install ruby

Installing R

Refer to the installation documentation:

https://www.graalvm.org/docs/getting-started/#running-r

./gu install R

Installing Python

Refer to the installation documentation:

https://www.graalvm.org/docs/getting-started/#running-python

./gu install python

Start Python:

graalpython

Compiling Java Programs to Executable Files

First, you need to install the native-image tool. Refer to:

https://www.graalvm.org/docs/reference-manual/native-image/#install-native-image

Once installed, you can use it according to the documentation, just like the HelloWorld program earlier.

// HelloWorld.java
public class HelloWorld {
  public static void main(String[] args) {
    System.out.println("Hello, World!");
  }
}

Compile and execute:

# Compile with Javac
$ javac HelloWorld.java

# Compile to native executable
$ native-image HelloWorld

# Execute directly
$ ./helloworld
Hello, World!

Seeing this, you might as well try it yourself, package your own projects like Spring Boot into executable files using GraalVM (currently not supported on Windows). Then take a look at the startup time, there will be a pleasant surprise.

Reference documentation:

https://www.graalvm.org/docs/getting-started/#native-images

Combining Multiple Languages

Please refer to the documentation:

https://www.graalvm.org/docs/reference-manual/polyglot/

References #