Go Native with Spring Boot 3 and GraalVM

October 16, 2022 | 6 minute read
Ewan Slater
Director of Technical Product Marketing, Java & GraalVM
Text Size 100%:

Introduction

There has been a lot of interest in the past few years about "native Java". You've probably read articles or seen conference talks on the subject.

TL;DR - "native Java"

Traditionally Java programs are compiled to bytecode. At runtime the bytecode is first interpreted and eventually compiled to native machine code by a JVM.

Native Java is the idea of using ahead-of-time (AOT) compilation to produce a native executable or "native image" for a Java application.

A native image can run standalone without relying on a JVM.

This approach potentially offers advantages in terms of:

  • faster application startup
  • lower latency
  • lower memory and CPU footprint and cost

GraalVM is an open source JDK that can compile Java applications to native images, as well as bytecode in the traditional way.

Native Java and Spring

Spring is the most popular Java application framework used today.

Over the last three years, the Spring and GraalVM teams have been working to make it easier for developers to deliver their Spring applications as native images.

Experimental support for native image was achieved via the Spring Native project.

With Spring Boot 3 and Spring 6 (due to be released November 24, 2022), support for native image will be available as a core feature.

Since the release candidate for Spring Boot 3 is now available, this seems a good time to try out the native image support.

Trying it out

So lets have a go at using the Spring Boot 3 release candidate and GraalVM to create a simple web application, compiled to a native executable.

Pre - requisites

You need to have GraalVM and it's native-image tool installed on your machine.

You can download these from here.

Note that you need GraalVM 22.3.0 and the equivalent version of native-image.

I'm using GraalVM Enterprise and native-image 22.3.0

GraalVM and native image versions

The Spring Boot App

The easiest way to get started with building a Spring Boot app is to use the spring initializr.

I'm going to walk through using both Maven and Gradle, so you can pick whichever one you pefer.

You can either enter the configuration by hand, or re use one of:

After choosing the build engine, I selected:

  • Spring Boot: 3.0.0 (RC1)
  • Language: Java
  • Artifact: Vanilla
  • Dependencies:
    • GraalVM Native Support
    • Spring Web

Once you are happy with your configuration click the "GENERATE" button.

Then copy the downloaded file to a directory of your choice, unzip it and cd into the vanilla directory.

Gradle

Start by running the application:

./gradlew bootRun

The application should start in a second or so:

 src="

You can to test the application:

curl localhost:8080

 src="

404 isn't a good look, so let's add a RestController to say something more meaningful.

Copy Hello.java from the code directory into ./src/main/java/com/example/vanilla (or write your own).

If we run the application (./gradlew bootRun) and test it (curl localhost:8080) again we should see a more meaningful response this time:

 src="

We can also build a stand alone jar:

./gradlew assemble

And run that:

java -jar ./build/libs/vanilla-0.0.1-SNAPSHOT.jar

Again you should see the app start in about a second:

 src="

So now we can take the next step and build our native image without having to make any changes to the project:

./gradlew nativeCompile

This may be a good opportunity to have a tea or coffee as it will take two or three minutes as opposed to a couple of seconds for building a jar (on my Mac, YMMV).

Once the build completes:

 src="

We can run the executable:

./build/native/nativeCompile/vanilla

You should see the application start in around ~0.1 seconds (so about 10x faster).

 src="

Looking at memory usage on my machine, the native image uses about 1/3 of the memory compared to running the application from the jar.

Maven

Before you start, make sure that $JAVA_HOME is set to point to your GraalVM installation:

$ $JAVA_HOME/bin/java --version
java 17.0.5 2022-10-18 LTS
Java(TM) SE Runtime Environment GraalVM EE 22.3.0 (build 17.0.5+9-LTS-jvmci-22.3-b07)
Java HotSpot(TM) 64-Bit Server VM GraalVM EE 22.3.0 (build 17.0.5+9-LTS-jvmci-22.3-b07, mixed mode, sharing)

Then run the application:

./mvnw spring-boot:run

The application should start in a second or so:

 src="

You can use curl localhost:8080 to test the application:

 src="

404 isn't a good look, so let's add a RestController to say something more meaningful.

Copy Hello.java from the code directory into ./src/main/java/com/example/vanilla (or write your own).

If we run the application (./mvnw spring-boot:run) and test it (curl localhost:8080) again we should see a more meaningful response this time:

 src="

We can also build a stand alone jar:

/.mvnw package

And run that:

java -jar ./target/vanilla-0.0.1-SNAPSHOT.jar

Again you should see the app start in about a second.

So now we can take the next step and build our native image without having to make any changes to the project:

./mvnw -Pnative native:compile

This may be a good opportunity as it will take two or three minutes as opposed to a couple of seconds for building a jar (on my Mac, YMMV).

Once the build completes:

 src="

We can run the executable ./target/vanilla

You should see the application start in around ~0.1 seconds (so about 10x faster).

 src="

Looking at memory usage on my machine, the native image uses about 1/3 of the memory compared to running the application from the jar.

Summary

So in summary, with Spring Boot 3.0, you can now easily leverage GraalVM Native image to build your applications as native executables.

Enjoy your faster startup, lower latency and lower infrastructure costs.

Ewan Slater

Director of Technical Product Marketing, Java & GraalVM

Ewan Slater is the Technical Director of Java & GraalVM product marketing at Oracle with over twenty years experience in the technology industry.

Ewan started programming in Java in 1997 and joined Oracle with the acquisition of Thor Technology in 2005.

His current focus is on helping Oracle’s customers and partners understand the technical benefits of Java and GraalVM.

He is involved with a number of open source projects, is a recovering conference organiser and a member of the Ipswich & Suffolk Technology Network (ISTN).

Outside of work, he can usually be found outdoors in the Suffolk countryside, or indoors in the kitchen.


Previous Post

Java Card at JavaOne 2022 in Las Vegas

Nicolas Ponsini | 2 min read

Next Post


Announcing GraalVM Enterprise 22.3

Shaun Smith | 4 min read