Supercharging Micronaut Applications with GraalVM

Unleashing the Power of Ahead-of-Time Compilation

Pradnya Karande
Globant
5 min readJan 30, 2024

--

What is GraalVM?

GraalVM is an innovative and high-performance JDK developed by Oracle, specifically designed to enhance the performance of Java applications while minimizing resource consumption.

This versatile platform offers two distinct methods for running Java applications:

JIT (Just-in-Time) Compilation

GraalVM integrates seamlessly with the HotSpot JVM, leveraging its Graal JIT compiler. This dynamic compilation approach optimizes the execution of Java bytecode at runtime.

Native Image Compilation

Another powerful feature of GraalVM is its ability to generate ahead-of-time (AoT) compiled native executables. With this approach, Java applications can be compiled ahead of time into highly optimized machine code, eliminating the need for a JVM during execution.

Besides Java, it provides runtimes for JavaScript, Ruby, Python, and a number of other popular languages. GraalVM’s polyglot capabilities make it possible to mix programming languages in a single application.

Runtime Modes

GraalVM is unique as a runtime environment offering several modes of operation: JVM runtime mode, Native Image, and Java on Truffle (the same Java applications can be run on either).

JVM Runtime Mode

When executing programs on the HotSpot JVM, GraalVM takes advantage of its powerful compiler, known as the GraalVM compiler, which serves as the default top-tier JIT compiler. During runtime, applications are loaded and executed in the standard JVM environment. The JVM receives bytecode, whether it’s for Java or any other language supported by the JVM, and passes it to the GraalVM compiler for optimization.

Native Image

Native Image is an innovative technology that compiles Java code into a standalone native executable or a native shared library. During the build process of a native executable, it processes the Java bytecode, which includes all application classes, dependencies, third-party libraries, and necessary JDK classes. The resulting native executable is self-contained, specific to the operating system and machine architecture it was built for and does not rely on a JVM for execution. This means the generated native executable can be run directly without needing a separate JVM installation.

Java on Truffle

The Java on Truffle execution mode enables the execution of Java code through a Java bytecode interpreter implemented using the Truffle framework. The Truffle framework, an open-source library designed for developing interpreters for various programming languages, facilitates the implementation of a performant and efficient interpreter for Java bytecode. This execution mode leverages the capabilities of Truffle to provide a seamless and reliable environment for executing Java code without the need for a traditional JVM-based execution model.

GraalVM Native Image

Native Image is a technology to compile Java code ahead of time to a binary — a native executable. A native executable includes only the code required at run time, that is, the application classes, standard library classes, the language runtime, and statically linked native code from the JDK.

  • Compiles Java code ahead of time to a binary — a native executable.
  • It includes Substrate VM — a slim VM implementation that provides runtime components, such as a garbage collector and a thread scheduler.
  • It includes only the code required at run time, e.g. Application classes and standard library classes.
  • Ideal for containers and cloud deployments.

Advantages of Native Image

  • Uses a fraction of the resources required by the Java Virtual Machine, so it is cheaper to run.
  • Starts in milliseconds.
  • Delivers peak performance immediately, with no warm-up.
  • It can be packaged into a lightweight container image for fast and efficient deployment.

Micronaut Support for GraalVM native Image

Any Micronaut application can be run using the GraalVM JVM; however, special support has been added to Micronaut to support running Micronaut applications using GraalVM’s native-image tool.

Since Micronaut 2.2, any Micronaut application can be built into a native image using:

  • Gradle
  • Maven plugins

Micronaut itself does not rely on reflection or dynamic class loading, so it works automatically with GraalVM native; however, certain third-party libraries used by Micronaut may require additional input about the uses of reflection. For such requirements, Micronaut includes an annotation processor that helps to generate reflection configuration that is automatically picked up by the native-image tool.

For a Micronaut application/microservices, the native image can be created with the following approaches:

Using Docker

$mvn package -Dpackaging=docker-native

Without Using Docker

  • Installing GraalVM.
  • Installing native-image tool.
  • mvn package -Dpackaging=native-image

Setting up GraalVM and native Image

Install GraalVM by following the instructions on this link: Install GraalVM.

  • Run the below command to generate a native image from the root directory or folder.
$mvn package -Dpackaging=native-image
  • Post successful execution of the above command, the native executable will be created in the target directory.
$ls /target/micronautguide
  • Run the native image executable below.
$./target/micronautguide

Here is what you see after running the native image executable.

  • You can execute the endpoint exposed by the native executables.
$curl localhost:8080/hello

Creating native executable inside Docker

  • Run the below command to generate a Docker image from the root directory or folder.
$mvn package -Dpackaging=docker-native

On successful execution, the above command should create a Docker image on the local machine.

  • Do verify with docker images command, it should create an image with the name micronautguide.
$docker images
  • Run the Docker image.
$docker run -p 8080:8080 micronautguide
  • You can execute the endpoint exposed by the native executable.
$curl localhost:8080/hello

Conclusion

GraalVM’s broad language support and polyglot capabilities empower developers to build versatile applications by seamlessly combining multiple programming languages. This flexibility, coupled with performance optimisations, encourages collaboration, code reuse, and the utilization of the best tools and libraries from different language ecosystems, ultimately enhancing development productivity and application performance.

--

--