GraalVM – Native Images – Getting Started

GraalVM is the hype in the Java world. It is a so called ‘Universal Virtual Machine’ that allows you to run all kinds of languages native on any host system. It profiles itself as an ‘High-Performance polyglot VM’. According to their website:

GraalVM is a universal virtual machine for running applications written in JavaScript, Python, Ruby, R, JVM-based languages like Java, Scala, Kotlin, Clojure, and LLVM-based languages such as C and C++. GraalVM removes the isolation between programming languages and enables interoperability in a shared runtime. It can run either standalone or in the context of OpenJDK, Node.js, Oracle Database, or MySQL. – https://www.graalvm.org/

Aside from the polyglot aspect, the GraalVM compiler also offers some interesting performance tweaks and possibilities. In this series of blog posts, I will take a look at the polyglot aspect of GraalVM and will investigate the possibilities and limitation of the native images that are generated by it. I will try and develop native image that can be deployed as a Java EE analog. I will start simple, and expand functionality to cover the following points:

  • A simple command line tool – We’ll do that as part of this post.
  • A simple web application with a REST endpoint
  • Dependency Injection and Inversion of Control
  • Database access

Each iteration will try to expand on the previous one if possible. In this first post, we’ll look at getting started with GraalVM and create a simple native command line tool. Before we get started though, it’s good to keep in mind the limitations of GraalVM at this point.

Limitations

The current and up-to-date list of limitations and their status can be found on the GitHub page of GraalVM. When looking at creating a Java EE native image, the most important here is the fact that GraalVM does not yet fully support Dynamic Class Loading and Reflection. Due to the nature of building the image ahead of time, it’s not possible to include or resolve any new classes at runtime. Features like lazy loading and the ability to infer types runtime is thus not possible. Looking at Java frameworks that offer Java EE functionality, like Spring Boot and Thorntail, we can already see some issue in trying to create a native images based on those. Both rely on reflection for their IoC implementation. We will need to get creative in order to reach or Java EE analog goals.

Getting GraalVM

The Getting Started section on GraalVM’s website is pretty expansive and will guide you through the process of getting and using GraalVM quite easily. Due to the active development of GraalVM, it might be wise to get more than one version of GraalVM. Just in case you run into a new bug or issues with the current version (hint: we will…). We have a few options here. You can use sdkman to manage your installations and switch when needed. Or you can use Docker to build your image with any GraalVM version. GraalVM offers it’s own docker images that you can use. Just make sure to grab the correct version by setting the correct tag on your image. Personally, I’ll mostly be using Docker for my tests when the code gets more complicated, just to prevent switching sdk for every performance test.

Simple Command line tool

Let’s create our simple command line tool to end with. To start, let’s verify that we installed GraalVM correctly:

$ java -version openjdk version “1.8.0_192” OpenJDK Runtime Environment (build 1.8.0_192-20181024121959.buildslave.jdk8u-src-tar–b12) GraalVM 1.0.0-rc10 (build 25.192-b12-jvmci-0.53, mixed mode

Next up, let’s create a simple Hello World in Java:

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


Compile this back boy with the GraalVM compiler:

$ javac HelloWorld.java

Run it, just to be sure that we can still write basic Java:

$ java -jar HelloWorld.jar

Hello World Let’s new create our native image from this jar file:

$ native-image -jar HelloWorld.jar

Run it:

$ ./HelloWorld

Hello World

You will notice that our HelloWorld executable is slightly larger then our .jar file. That’s of course because GraalVM included everything needed to run our Java code, without actually using Java on the host system. You can check this by copying the GraalVM executable over to another system and executing it. Given that you’re running the same OS and architecture, it should run just fine and print “Hello World” without issues. In the next installment of this series, I’ll try to setup a simple REST API as a native image. I’ll also do a comparison in performance between the native image and the Java application.