# 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**](https://ankurm.com/building-native-images-of-spring-boot-applications-with-graalvm-a-step-by-step-guide/) 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](docs/01-versions-and-setup.md) for how each version claim here was checked. ## Quickstart ```bash # 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](docs/01-versions-and-setup.md) | Verified version claims; why `gu install native-image` is obsolete | | [02-building-the-image.md](docs/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](docs/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](docs/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/](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 14s–4m 19s on 2 vCPU / 8 GB | Full transcripts: [docs/output/01-jvm-baseline.txt](docs/output/01-jvm-baseline.txt), [docs/output/02-native-build.txt](docs/output/02-native-build.txt), [docs/output/05-native-startup-fixed.txt](docs/output/05-native-startup-fixed.txt).