Java programs as native executables: GraalVM is the answer!

0

TL;DR:

•    Using GraalVM Java applications can be compiled into native standalone executables (will be demonstrated).
•    Native executables of small Java programs startup blazingly fast, use considerably less resources compared to running on JVM and do not even require the JRE or any other kind of runtime apart from the OS.
•    Running Java applications as native standalone executables provides opportunities for lean usage of Java in serverless functions, cloud deployment and microservices.

GraalVM, Please Explain

GraalVM started over decade ago as a Sun Microsystems research project. It was subsequently adopted by Oracle Labs and has now reached a stage where it can go out into the wild. GraalVM is a polyglot VM, meaning it can run programs in many different languages at faster paces, usually, than the original specialized runtimes. It allows for interoperability between diverse components in distinct languages as well. For more information see their website.

GraalVM is stated to be(come) the one VM to rule them all. Sounds promising, right? Well, it is! And it’s in active development, so if it’s not perfect yet, you can wait for it to shortly provide what you need!

Java Moving in a Forward Direction

Java is a considered a heavy language – meaning that it is resource intensive. Applications are large – on disk and in memory – and startup time is drawn-out. Already improvements have been made in the newer versions of Java, such as the modular Java runtime (Java 9) and the currently experimental ahead-of-time compiler (jaotc, using Graal) tool in Java 9 (based on JEP 295). Now with GraalVM it’s possible to convert a Java application into a standalone native executable that does not need a Java runtime at all.

Towards Java Native Standalone Executables

Example: A Java application

I’ve been testing GraalVM by following an article from the GraalVM team and later tried another small Java program, which I ran as a native executable. The additional code I used for a URL connection and it requires several libraries. The code is opening the website of my old research group “the Bonvin lab” in a Firefox browser (since the code didn’t run without specifying this). It is then scanning the text inside the webpage, counting all words in between spaces and printing the total wordcount. It’s a piece of code adapted from this webpage.

import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.Scanner;

public class URLExpSimple {

    public static void main(String[] args) {
        try {
            URL mySite = new URL("http://www.bonvinlab.org/education/research-projects/");
            URLConnection yc = mySite.openConnection();
            yc.addRequestProperty("User-Agent", "Mozilla/5.0");
            Scanner in = new Scanner(new InputStreamReader(yc.getInputStream()));
            int count = 0;
            while (in.hasNext()) {
                System.out.println(in.next());
                count++;
            }
            System.out.println("Number of tokens: " + count);
            in.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}     

Creating a native executable

For comparison, I first did the traditional thing: I compiled the Java source to a Java main class which I can then run with the JRE and the Java JIT:

$ javac URLExpSimple.java
$ time java URLExpSimple
…..
Number of tokens: 1032
real	0m1,140s
user	0m0,687s
sys		0m0,052s

In this way, first the Java Runtime is started, and then the JIT compiler is translating from Java byte-code to the platform specific machine code. Then finally, the script is executed. This consumes quite a bit of CPU and requires a lot of memory to execute – as is shown below.
However, I could use the GraalVM to create a native standalone executable using this command:

$ native-image -H:EnableURLProtocols=http --no-server URLExpSimple

Using the -H:EnableURLProtocols=http flag, I can enable the use of http-URLs. The only protocol enabled by default is the file-protocol, and the reason behind this is to start with a minimal image (small overall size) and expand it with features you truly need.

$ ls -inh urlexpsimple
1057578 -rwxr-xr-x 1 1000 1000 9,0M aug 20 10:26 urlexpsimple

The command takes some time to complete – eventually producing this newly created native executable that is significantly bigger than the original Java application – but is completely stand alone and does not require a Java runtime environment – think what that will do to the size of your container or Serverless Function!

Comparing the native executable with running on JVM

Now, the native standalone executable is ready to run without requiring the Java Runtime.

$ time ./urlexpsimple
…..
Number of tokens: 1032
real	0m0,042s
user	0m0,00s
sys		0m0,008s

The real time used for the native executable was only half the time it took the Java program to run.  If we look at more specifics, we see several things:

</pre>
$ /usr/bin/time -v java URLExpSimple
> CPU usage of the job: 75%
> Maximum resident set size (kbytes): 58972 //rss
> Voluntary context switches: 799
> Involuntary context switches: 2884
> File system outputs: 72

$ /usr/bin/time ./urlexpsimple
> CPU usage of the job: 23%
> Maximum resident set size (kbytes): 10008 //rss
> Voluntary context switches: 3
> Involuntary context switches: 1107
> File system outputs: 0

Here you see a major decrease in CPU and RAM memory (Memory, rss) usage by the execution of the application, since for small applications this is mostly taken up by the Java Runtime. As for the efficiency of the execution, the native standalone executable causes less CPU context switches, meaning it switches less between different threads and the current executing thread and is therefore more efficient.

When I transferred the native executable from my Ubuntu to a Kubuntu Linux distribution, the native standalone executable ran immediately without any problems.

Advantages and Opportunities for Java

The use of GraalVM provides opportunities for Java in cloud deployment, microservices and serverless usages where you only pay for the actual amount of time and memory that are used by the application to run instead of renting pre-determined capacity units. The order of magnitude of faster startup time  with Java-as-native-executable is also of great value with dynamically scalable containers and even more so with serverless functions.
The old Java motto write once, run anywhere still holds, although in all fairness it should now read write once, build, then run anywhere.

Concluding Remarks

To sum up, I’ve created a native standalone executable from a Java application that imports various Java SE classes. This executable  can be used easily without any installation or configuration problems, which is pretty awesome. Additionally, the expected advantages in fast startup and low footprint are enormous and should pique your interest. If you were thinking Java has had its best time, then you should wait, reconsider and see what GraalVM will bring us in the future. Since surely, the aim of GraalVM is to become the fastest VM for all languages.

My next blog will be about the polyglot elements in GraalVM and its value from an interoperability point of view, so stay tuned!

System specs:

GraalVM was running on a guest 64-bit Ubuntu 18.04.1 Linux distribution on VitrualBox VM, with 4 GB RAM and 1 core CPU, with a Windows-10 16GB RAM host.

Download GraalVM > https://www.graalvm.org/.
More GraalVM > https://www.youtube.com/watch?v=tEaEAq0L9Pk.
Want to try it yourselves? > https://medium.com/graalvm/graalvm-ten-things-12d9111f307d
Want to try out my native standalone executable on your Linux distribution? > urlexpsimple
About URL protocols in GraalVM > https://github.com/oracle/graal/blob/master/substratevm/URL-PROTOCOLS.md.
More about serverless model > https://serverless.com/learn/.
Want to know more about GraalVM and serverless opportunities? > https://medium.com/criciumadev/serverless-native-java-functions-using-graalvm-and-fn-project-c9b10a4a4859
The code I used adapted from > https://www.cs.utexas.edu/~scottm/cs307/codingSamples.htm.

About Author

I'm inspired by people, and interested in people, science and technology. I have an interdisciplinary background through studies in Liberal Arts and Sciences and Molecular and Cellular Life Sciences. I dive into a subject, learn it, love it, own it, and move on to the next challenge.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.