Try GraalVM Now!
Bishoy Basily
Senior Software Engineer | Java | Kubernetes | Spring | Apache Spark | Android | Kotlin
In this quick guide, we will explore the AOT (ahead of time) Compilation that GraalVM provides to compile Java and other JVM language sources into a platform-dependent native binary, with a very low memory footprint and doesn't need the Java Runtime to run.
What is GraalVM?
GraalVM – a high-performance multilingual runtime. It is designed to accelerate the execution of applications written in Java and other JVM languages while also providing runtimes for JavaScript, Ruby, Python, and a number of other popular languages.
Now, Let's get started, the installation steps are available here for all platforms.
If you don't want to waste your time extracting archives and modifying variables, I've prepared a docker image with all you need to try GraalVM with Java as well as Scala, here is the Dockerfile on Github.
First, Run the container
docker run --rm -v /temp:/temp/ -it bishoybasily/graalvm-ce:11-focal
We will use this mounted temp volume later to share our binary with another Linux container to test the generated native binary file.
Now, inside the temp directory create a Main.java file with a simple main method, prints anything.
cat > /temp/Main.java <<EOL public class Main { public static void main(String[] args) { System.out.println("Hello Java Native!"); } } EOL
Let's try to run this java file.
cd /temp/ && java Main.java
It will output "Hello Java Native!".
Now, let's compile this java file into a Main.class file.
javac Main.java
Finally, let's build a native binary from this classpath. the native-image CLI tool that comes with GraalVM is responsible for doing that.
native-image -cp . Main -H:Name="myJavaNativeApp"
The previous command does the following:
- -cp . (tells the native image that our classpath is the current directory, the temp directory that contains the .class file/s)
- Main (specifies the class that contains the main method for our app)
- -H:Name="myJavaNativeApp" (specifies the out file name which gonna be "myJavaNativeApp")
This command will take few moments to build our native binary, now try to run the generated "myJavaNativeApp"
./myJavaNativeApp
You will get the same output "Hello Java Native!"
To verify that our binary doesn't need any specific runtime for execution other than a Linux OS, let's try the same binary on another Linux container, centos for example.
docker run --rm -v /temp:/temp/ -it centos:8
Again, cd into the temp directory and try to run the binary file.
The jar files are supported as well as the classpath, let's try it
jar -cfe app.jar Main -C /temp/ .
Again, generate a new binary but this time from a jar.
native-image -jar app.jar -H:Name="javaBinary"
We just replaced the -cp "path/to/classpath" with -jar "path/to/file.jar"
The same previous steps can be done with scala sources, the only difference is that you'll need to include the scala-library.jar to your classpath while compiling it.
Create a scala file.
cat > /temp/ScalaMain.scala <<EOL object ScalaMain extends App { println("Hello Scala Native!") } EOL
Compile it.
scalac ScalaMain.scala
And finally, generate the native image, but remember to add the scala library to your classpath
native-image -cp .:$SCALA_HOME/lib/scala-library.jar ScalaMain -H:Name="myScalaApp" --no-fallback
The previous command does the following:
- -cp .:$SCALA_HOME/lib/scala-library.jar (specifies the classpath to be the current directory along with the scala-library.jar)
- ScalaMain (specifies the class with the main method)
- -H:Name="myScalaApp" (specifies the output file name)
- --no-fallback (prevents generating a binary that depends on the current java runtime if generating the standalone binary file fails)
Great! we did it.
If your apps target platforms with a limited set of resources like RaspberryPI for instance, this will significantly improve your experience in this part.
Check how Quarkus uses GraalVM to build super-fast web applications, Spring also started to adopt GraalVM but the implementation is currently in beta.
Thanks for Reading! :)