skip to content

AOT & Native Image

Ahead-of-time processing and GraalVM native images: what AOT generates, the closed-world constraints, reachability hints, build tooling, testing, and the startup and footprint trade-offs. Interviewers ask because 'make it start faster' is a real requirement in serverless and scale-to-zero setups.

part ofSpring Frameworkoverview, primer and where to startread it →
on this pageshow

explore

questions

145 · 6 sections

What are the generated `*__BeanDefinitions` source classes that Spring's AOT engine produces at build time, and why are they created?

level: juniorimportance: must knowfreq 55%
basics
~20 s

During an AOT build, Spring generates plain Java classes named like MyService__BeanDefinitions that build each bean's definition in explicit code instead of scanning and reflecting at startup. This lets GraalVM native images work without runtime reflection.

open as a page

What does it mean that Spring AOT 'freezes' conditions and the bean set at build time?

level: juniorimportance: must knowfreq 55%
basics
~20 s

During an AOT build Spring evaluates all @Conditional/@Profile checks and auto-configuration once, decides which beans exist, and generates code registering exactly those beans. Those decisions are fixed; they are not re-checked when the app runs.

open as a page

How does Spring discover and register a custom BeanRegistrationAotProcessor or BeanFactoryInitializationAotProcessor?

level: middleimportance: must knowfreq 40%
basics
~10 s

Two ways: list the implementing class in META-INF/spring/aot.factories under the SPI interface name, or register a bean that implements the interface — Spring auto-detects such beans during AOT processing.

open as a page

What is an instance supplier in AOT-generated bean definitions, and how does it replace reflective bean instantiation?

level: middleimportance: must knowfreq 50%
basics
~20 s

An instance supplier is a callback set on the BeanDefinition (via setInstanceSupplier) that creates the bean by directly calling its constructor or factory method in generated code, instead of Spring reflectively finding and invoking the constructor at runtime.

open as a page

Why does changing spring.profiles.active at runtime fail to swap beans in an AOT / native Spring Boot app?

level: middleimportance: must knowfreq 60%
basics
~20 s

Because @Profile is a condition. AOT evaluates profiles at build time and bakes in only the beans for the profiles active then. Activating a different profile at runtime cannot add beans that were never generated.

open as a page

In GraalVM native image, what is the difference between --initialize-at-build-time and --initialize-at-run-time?

level: juniorimportance: must knowfreq 70%
basics
~20 s

--initialize-at-build-time runs a class's static initializer while the image is being built, baking the resulting state into the binary. --initialize-at-run-time defers it to when the app actually starts, so it runs fresh on each launch.

open as a page

What is the closed-world assumption in GraalVM native image, and what does it mean for a Spring application?

level: juniorimportance: must knowfreq 62%
basics
~20 s

GraalVM analyzes your whole app at build time and includes only the code it can prove is reachable. Nothing new can be loaded at runtime, so the native executable is a fixed, self-contained set of classes and methods.

open as a page

Why are CGLIB (class-based) proxies problematic in a GraalVM native image, and what does Spring prefer instead?

level: juniorimportance: must knowfreq 62%
basics
~10 s

CGLIB creates proxy classes at runtime by generating new subclasses. A native image is closed at build time and cannot generate classes at runtime, so CGLIB proxies fail. Spring prefers JDK/interface-based proxies instead.

open as a page

Why does reflection often break when you compile a Spring application to a GraalVM native image?

level: juniorimportance: must knowfreq 70%
basics
~20 s

GraalVM native image builds a closed world: it only includes code it can see is used at build time. Reflection resolves types/methods at runtime, so unless that reflective access is declared up front, the elements are dropped and calls fail.

open as a page

In a GraalVM native image, why do classpath resources (like a .txt or .sql file loaded via ClassPathResource) sometimes fail to load at runtime, and what fixes it?

level: juniorimportance: must knowfreq 70%
basics
~20 s

GraalVM's closed-world build only bundles resources it knows about. Files loaded reflectively at runtime aren't detected, so they're dropped. You must register them (via resource-config.json or Spring ResourceHints) so the build includes them in the image.

open as a page

What is Spring's RuntimeHints, and what are the main categories of hints it exposes?

level: juniorimportance: must knowfreq 55%
basics
~10 s

RuntimeHints is a Spring object that records what a native image needs kept at runtime. It groups hints into sub-APIs: reflection, resources, JDK proxies, serialization, and JNI — each feeding a GraalVM config file.

open as a page

What does the @ImportRuntimeHints annotation do in a Spring application?

level: juniorimportance: must knowfreq 45%
basics
~20 s

@ImportRuntimeHints is placed on a @Configuration class or bean to register one or more RuntimeHintsRegistrar classes. During AOT/native-image build, Spring calls those registrars so they can declare reflection, resource, and proxy hints the GraalVM compiler needs.

open as a page

What is the GraalVM reachability-metadata repository and why does a native Spring Boot build need it?

level: juniorimportance: must knowfreq 60%
basics
~20 s

It is a community-maintained collection of GraalVM native-image config (reflection, resources, proxies) for popular third-party libraries. The build tool pulls the right config so those libraries work in a native image without you writing hints by hand.

open as a page

What is a RuntimeHintsRegistrar in Spring, and why do you need one when building a GraalVM native image?

level: juniorimportance: must knowfreq 55%
basics
~20 s

It is an interface where you tell the native-image build which classes, resources, or proxies your app uses via reflection. GraalVM closes the world at build time, so anything discovered dynamically must be declared, or it fails at runtime.

open as a page

How do you register reflection hints with ReflectionHints, and what does MemberCategory control?

level: middleimportance: must knowfreq 60%
basics
~10 s

Use hints.reflection().registerType(MyType.class, category...). MemberCategory selects which members become reflectively accessible — e.g. declared constructors, public/declared methods, or fields. It maps to reflect-config.json.

open as a page

What does the Spring Boot bootBuildImage task do, and how do you make it produce a native-image container?

level: juniorimportance: must knowfreq 55%
basics
~10 s

bootBuildImage is a Spring Boot build task that packages your app into a Docker/OCI container using Cloud Native Buildpacks. To build a native executable inside it, set the environment variable BP_NATIVE_IMAGE=true for the buildpack.

open as a page

What is the GraalVM native-build-tools Gradle plugin, and which tasks does it add to a Spring Boot build?

level: juniorimportance: must knowfreq 55%
basics
~10 s

It's the Gradle plugin org.graalvm.buildtools.native that lets you compile a GraalVM native image locally. It adds tasks like nativeCompile (build the native executable) and nativeRun (run it).

open as a page

What is the GraalVM native-maven-plugin and how do you use it to build a native image of a Spring Boot app with Maven?

level: juniorimportance: must knowfreq 60%
basics
~10 s

It's the GraalVM native-build-tools Maven plugin that compiles your app into a native executable. In Spring Boot you run mvn -Pnative native:compile; the native profile plus its native:compile goal invoke GraalVM's native-image compiler.

open as a page

What is the GraalVM native-image-agent and what problem does it solve?

level: juniorimportance: must knowfreq 55%
basics
~20 s

It is a JVM agent (enabled with -agentlib:native-image-agent) that watches an app running on the normal JVM and records dynamic behavior like reflection, resource loading and proxies, writing JSON metadata that native-image needs to compile those parts.

open as a page

Explain how spring-boot process-aot and native:compile are bound in the Maven lifecycle, and why the ordering matters.

level: middleimportance: must knowfreq 45%
basics
~20 s

In the native profile, Spring Boot binds its process-aot goal to run during the build's earlier phases; native:compile (bound around the package phase) runs after it. process-aot generates bean code and reachability hints that native-image needs, so it must run first.

open as a page

Why are tests using @MockitoBean / @MockBean typically incompatible with AOT mode, and how does @DisabledInAotMode help?

level: middleimportance: must knowfreq 45%
basics
~20 s

@MockitoBean and @MockBean replace a real bean with a mock by changing the application context. An AOT-built context is frozen and cannot be changed, so the mock cannot be installed. @DisabledInAotMode skips such tests when running in AOT mode.

open as a page

You've generated the AOT test artifacts. How do you actually run your tests against the AOT-optimized context on the JVM, and why would you do that instead of building a native image?

level: middleimportance: must knowfreq 45%
basics
~20 s

Set the system property spring.aot.enabled=true when running the test task. The TestContext framework then loads the build-time generated context instead of refreshing a fresh one. You do this on the JVM because it's far faster than a native build for catching AOT problems.

open as a page

Write a test that asserts a registrar registered reflection access to a type's declared constructors.

level: middleimportance: must knowfreq 45%
basics
~10 s

Run the registrar against a fresh RuntimeHints, then assert RuntimeHintsPredicates.reflection().onType(MyType.class).withMemberCategory(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS) accepts those hints using AssertJ's .accepts(hints).

open as a page

What is @DisabledInAotMode and what problem does it solve in Spring tests?

level: juniorimportance: should knowfreq 25%
basics
~10 s

It is a Spring test annotation that skips a test when the app runs in AOT (ahead-of-time) mode. You put it on tests whose setup does not work with an AOT-optimized, pre-built application context.

open as a page

What are AOT-mode tests in Spring, and what does the process-test-aot / processTestAot step actually do?

level: juniorimportance: should knowfreq 35%
basics
~20 s

AOT (ahead-of-time) test processing pre-builds each test's Spring ApplicationContext at build time instead of at runtime. The processTestAot task (Gradle) or process-test-aot goal (Maven) generates that code so tests can run against a pre-optimized context.

open as a page

What do you gain by compiling a Spring Boot app to a GraalVM native image instead of running it on the JVM, in terms of startup and memory?

level: juniorimportance: must knowfreq 70%
basics
~10 s

A native image starts in tens of milliseconds instead of seconds, and uses much less memory (RSS), because the app is compiled ahead-of-time to a native executable with no JVM warm-up.

open as a page

Walk through the Profile-Guided Optimization (PGO) workflow for a Spring Boot native image. What are the steps and what file is produced?

level: middleimportance: must knowfreq 50%
basics
~10 s

Three steps: build an instrumented binary with --pgo-instrument, run it under a realistic workload to produce a profile file (default.iprof), then rebuild passing --pgo=default.iprof so the compiler optimizes the hot paths. Requires Oracle GraalVM.

open as a page

Why can a warmed-up JVM out-perform a GraalVM native image on peak throughput, and what mitigates that gap?

level: middleimportance: must knowfreq 60%
basics
~20 s

The JVM's JIT compiler profiles running code and re-optimizes hot paths, so after warm-up it can run faster. A native image is compiled once ahead-of-time with no runtime profiling, so its peak throughput is often lower. Profile-Guided Optimization (PGO) narrows the gap.

open as a page

How do you handle open resources (DB connections, sockets) across a CRaC checkpoint/restore in a Spring app?

level: seniorimportance: must knowfreq 38%
basics
~10 s

Implement org.crac.Resource: in beforeCheckpoint() close/drain the resource (e.g. evict a connection pool); in afterRestore() re-open it. Register with Core.getGlobalContext().register(this). Spring already does this for its managed Lifecycle beans and many pools support it.

open as a page

Explain the 'closed-world assumption' of native image and how it constrains a Spring application at build and run time.

level: seniorimportance: must knowfreq 55%
basics
~20 s

Native image assumes a closed world: every class, reflective call, resource, and proxy that will ever run must be known at build time. Anything discovered dynamically at runtime (unregistered reflection, runtime classpath additions, dynamic proxies) simply isn't there and fails.

open as a page