Files
spring-boot-demo/graalvm-native-images

GraalVM native images of a Spring Boot 4.1 application

Companion project for GraalVM Native Images for Spring Boot 4.1: AOT Processing, the Tracing Agent, and a Real Reflection Failure on ankurm.com.

A small Spring Boot 4.1 web app, built and run three ways -- a plain java -jar, the same jar with Spring's AOT processing applied, and a GraalVM native image -- with every startup time, memory number, and failure message in this README and the linked post captured from a real run, not estimated.

Versions

Spring Boot 4.1.1
JDK (JVM runs) Temurin 25.0.4.1
GraalVM (native builds) GraalVM Community Edition for JDK 25, build 25.0.2+10.1
native-maven-plugin 1.1.8 (pinned by spring-boot-starter-parent:4.1.1's dependency management; 1.1.14 is the latest on Maven Central as of this writing, but the parent's pinned version is what actually runs unless overridden)

The previous version of this project and its post assumed Spring Boot 3.x, JDK 17, and GraalVM 22.3 -- two major generations behind. See docs/01-versions-and-setup.md for how each version claim here was checked.

Quickstart

# 1. Plain JVM run (any JDK 25 build)
mvn -DskipTests package
java -jar target/app.jar

# 2. Native image (needs a GraalVM distribution -- native-image ships bundled, no `gu install` step)
export JAVA_HOME=/path/to/graalvm-25.0.2
mvn -Pnative -DskipTests native:compile   # NOT `mvn -Pnative package` -- see docs/02-building-the-image.md
./target/graalvm-native-images

What's in this chapter

Doc Covers
01-versions-and-setup.md Verified version claims; why gu install native-image is obsolete
02-building-the-image.md AOT processing's real generated output; why -Pnative package alone does not build a native image
03-the-reflection-trap.md A real ClassNotFoundException from a runtime-computed Class.forName, the tracing-agent fix, and the metadata-collision trap that fix runs into
04-honest-limits.md What native images cost you, and where Project Leyden fits as the non-full-native alternative

Every number quoted in the post is in docs/output/ as a trimmed, real transcript.

Measured, not estimated

plain JVM native image
Startup ("Started ... in") 3.472 s 0.091 s (0.104 s with reflection hints added)
RSS at idle ~190.8 MB ~105.5 MB
Artifact size 22 MB jar (+ a JDK install) 93 MB self-contained executable
Build time ordinary mvn package 4m 14s4m 19s on 2 vCPU / 8 GB

Full transcripts: docs/output/01-jvm-baseline.txt, docs/output/02-native-build.txt, docs/output/05-native-startup-fixed.txt.