GraalVM – An Introduction to the Next Level JVM

Last Updated:  August 6, 2021 | Published: March 12, 2019

With Red Hat announcing Quarkus as a …

next-generation Kubernetes native Java Framework tailored for GraalVM and HotSpot, crafted from best-of-breed Java libraries and standards.

I was impressed by the startup speed and memory consumption of the examples provided by Red Hat. One of the main reasons for these impressive numbers is that the code is ahead-of-time (AOT) compiled to a native image with GraalVM, an extension of the Java virtual machine developed by Oracle. To help you to understand the differences between the classic HotSpot JVM and the GraalVM better, I'll present you GraalVM with its features and its history in this blog post.

TL;DR: GraalVM is an extension of the JVM written in pure Java, developed by Oracle and supporting a polyglot programming model and ahead-of-time compilation.

History of the HotSpot Java Virtual Machine

The HotSpot JVM was the main Java virtual machine maintained and distributed by Oracle to run Java programs for many years. The Java HotSpot Performance Engine was released in 1999 and initially developed by Animorphic, a company acquired by Sun Microsystems and now owned by Oracle. This virtual machine is written mainly in C/C++ and is getting more and more complex (estimated 250.000 lines of code in 2007).

The main purpose of the HotSpot JVM is to run Java bytecode (.class files) and continuously analyze the program's performance for so-called hot spots within the program, which are executed often and to just-in-time (JIT) compile them to native code (machine code) for improved performance. This is done during runtime rather than before the execution of the Java program and, therefore just-in-time.

The workflow for running Java code within the HotSpot JVM looks like the following (simplified):

HotSpot JVM JIT (just-in-time) compilation overview

The HotSpot virtual machine mainly interprets the provided Java bytecode, but also just-in-time compiles bytecode to native machine code when appropriate parts of the application are found during the analysis of the program's runtime.

When a method is compiled with the JIT compiler, the JVM will execute the machine code directly for any further method calls instead of interpreting it and improving performance. As the compilation of native codes takes CPU time and memory, the JVM has to decide which methods to compile during runtime. Compiling all methods directly to native code would affect the performance.

Changes with the release of Java 9

With Java 9 and specifically the JEP 295, the JDK got an ahead-of-time compiler jaotc.  This compiler uses the OpenJDK project Graal for backend code generation. The motivation behind this step was the following:

JIT compilers are fast, but Java programs can become so large that it takes a long time for the JIT to warm up completely. Infrequently-used Java methods might never be compiled at all, potentially incurring a performance penalty due to repeated interpreted invocations Motivation of JEP 295

The Graal OpenJDK project demonstrates that a compiler written with pure Java can generate highly optimized code. With this AOT compiler and Java 9, you can manually ahead-of-time compile Java code. That means generating machine code before execution and not during runtime as with a JIT compiler, first experimental.

This will improve start-up time as the JIT compiler does not have to intercept the program's execution. The main downside of this approach is the platform-depended native code. This may lead to a platform lock for this AOT compiled code.

AOT compiling with Java simplified

The Architecture GraalVM

Based on the Graal compiler, Oracle started to develop the GraalVM to avoid working with the big and complex C/C++ codebase of the HotSpot JVM but also tackle the current polyglot movement with a virtual machine written in Java.

The architecture of the GraalVM looks like the following:

Available programming languages within GraalVM

GraalVM structure

The first thing you may notice is the presence of several non-JVM languages. You can now run code using Ruby, R, or JavaScript within this universal virtual machine. To achieve this, the Truffle framework is used. Truffle is an Open Source library for building programming language implementations as interpreters for self-modifying Abstract Syntax Trees (read here for a more detailed explanation). With this feature, you can now write and execute, e.g., JavaScript code within your Java codebase.

In addition, GraalVM offers the following feature for ahead-of-time compilation to native executables:

GraalVM allows you to compile your programs ahead-of-time into a native executable. The resulting program does not run on the Java HotSpot VM, but uses necessary components like memory management, thread scheduling from a different implementation of a virtual machine, called Substrate VM. Substrate VM is written in Java and compiled into the native executable. The resulting program has faster startup time and lower runtime memory overhead compared to a Java VM. GraalVM on AOT

Compile and Run A First Java Program With GraalVM

As of writing this blog post, there are two editions of the GraalVM: Community Edition (CE) and Enterprise Edition (EE), both only for Mac OS X and Linux. To use GraalVM on Windows during development, you can use the official Docker image from Oracle, which is used in the following examples.

Imagine the following simple HelloWorld class:

Before GraalVM and Java 9's AOT compiler, you executed this code like the following:

With GraalVM, you can now choose to either run your application using the already existing way (HotSpot JVM) or create a native image with the GraalVM AOT compiler and run an executable:

With this HelloWorld example, the improved performance is insignificant, but in a larger and more realistic application, the performance improvements are remarkable (see Quarkus).

A nice example of a simple polyglot application can be found in the official GraalVM Getting Started Guide:

This Java class is responsible for pretty-printing JSON and makes use of the JavaScript methods JSON.parse() and JSON.stringify() .

We can build a native image of this class like the following:

The performance difference between running the native image and running the application within HotSpot is now measurable:

In my opinion, Oracle does a really great job with GraalVM towards Java's dominance as a programming language. Furthermore, this initiative improves the sustainability and feature development of the Java language itself. Having a polyglot architecture also increases the adoption of other programming languages.

You can find the examples within my GitHub repository and try it on your machine with either GraalVM directly (Mac & Linux) or with Docker on Windows (make sure to give Docker at least 6 GB of RAM and 2 – 4 cores).

Happy JIT or AOT compiling,

Phil

 

  • {"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}
    >