the tracing agent, and a real reflection-collision trap Co-Authored-By: Claude Sonnet 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01EQNA6DJ9VgCtW6zhCE8Xud
61 lines
3.0 KiB
Markdown
61 lines
3.0 KiB
Markdown
# 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).
|