How does the reachability-metadata repository relate to Spring's RuntimeHints mechanism, and when do you still need to write your own hints?
answer
- Repository = libraries; RuntimeHints = your code + framework
- RuntimeHintsRegistrar + @ImportRuntimeHints
- @RegisterReflectionForBinding for DTO binding
- Gaps: no coverage, wrong version, partial paths
- Tracing agent bootstraps missing metadata
basics
~10 sThe repository supplies metadata for third-party libraries; Spring's RuntimeHints (RuntimeHintsRegistrar, @ImportRuntimeHints, @RegisterReflectionForBinding) supplies hints for your own and framework code. You still hand-write hints for application-specific reflection the repository can't know about.
solid answer
~40 sThey cover different domains and combine into one native-image config. The GraalVM reachability-metadata repository is community/vendor-maintained metadata for *libraries*, matched by coordinates and merged by Native Build Tools. Spring's `RuntimeHints` API is emitted during Spring's AOT processing for *your application and framework beans*: `RuntimeHintsRegistrar` implementations wired via `@ImportRuntimeHints`, plus conveniences like `@RegisterReflectionForBinding` and `@RegisterReflection`. Spring also infers many hints automatically from bean definitions. You still write your own hints when: a library isn't in the repository or your version has no entry; the library is covered but your usage triggers a reflective path its metadata doesn't include; or your own code loads classes/resources reflectively or serializes types. In short: repository = other people's jars; RuntimeHints = your code, framework glue, and the gaps the repository leaves.
code
java · 23 linesimport org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.aot.hint.MemberCategory;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportRuntimeHints;
// Hints for YOUR reflective code / a library the repository doesn't cover.
@Configuration
@ImportRuntimeHints(AppRuntimeHints.class)
public class AppConfig {
}
class AppRuntimeHints implements RuntimeHintsRegistrar {
@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
// A class instantiated reflectively in your code:
hints.reflection().registerType(com.example.LegacyPlugin.class,
MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS,
MemberCategory.INVOKE_PUBLIC_METHODS);
// A classpath resource loaded by name at runtime:
hints.resources().registerPattern("templates/report.mustache");
}
}go deeper
Should know both exist and cover different things.
Should name RuntimeHintsRegistrar/@ImportRuntimeHints and the repository's library scope.
Should diagnose coverage gaps and choose repository vs. hand-written hints, using the tracing agent.
Should set org-wide policy: when to contribute upstream vs. maintain local hints, and how to detect drift.
**Two sources, one output.** A native image is configured from merged reachability metadata. Spring Boot native builds draw that config from two complementary sources: 1. **GraalVM reachability-metadata repository** — external, community/vendor-maintained JSON metadata for third-party *libraries*, matched by `group:artifact:version` and merged by GraalVM Native Build Tools' `metadataRepository` feature. You author nothing; you consume tested metadata. 2. **Spring's `RuntimeHints`** — hints for *your application code and framework integration*, produced during **Spring AOT processing** (the `process-aot` phase run by the Spring Boot build). Key APIs: - `RuntimeHintsRegistrar` — implement `registerHints(RuntimeHints, ClassLoader)` and register reflection/resource/proxy/serialization hints programmatically; wire it with `@ImportRuntimeHints(MyHints.class)` on a `@Configuration` class or component. - `@RegisterReflectionForBinding(Foo.class)` — declaratively register a type (and its members) for reflective binding, e.g. Jackson/validation of DTOs. - `@RegisterReflection` — finer-grained declarative reflection registration. - Automatic inference: Spring registers many hints itself from bean definitions, `@Configuration`, `@ConfigurationProperties`, controllers, etc., so you often need nothing. **Division of labor.** Repository = libraries you don't own. RuntimeHints = your own reflective code + framework wiring + anything the repository misses. They don't conflict; both feed the same native-image config and are additive. **When you still hand-write hints.** - **No coverage:** a library isn't in the repository, or the repository's snapshot has no entry for *your* version (a newer release than the metadata knows about). - **Partial coverage:** the library is covered, but your particular usage exercises a reflective branch (e.g. an optional codec, an SPI) whose metadata wasn't captured — you'd add the missing reflect/resource hints yourself. - **Your own dynamic code:** you call `Class.forName`, load a classpath resource by name, build a JDK proxy, or serialize a type. The repository can't know about application-specific behavior; you declare it via `RuntimeHintsRegistrar` or the annotations. - **Corrections:** when library metadata is wrong for your case, you may exclude it (Native Build Tools filtering) and provide your own. **Diagnosing gaps.** The GraalVM **tracing agent** (`-agentlib:native-image-agent`) can observe a running app on the JVM and emit metadata for whatever it exercised — useful to bootstrap hints for uncovered code, which you then curate into a `RuntimeHintsRegistrar` or contribute upstream. **Mental model.** Think of the repository as a shared, versioned 'library metadata registry' and `RuntimeHints` as your app's local overrides/additions. Correct native builds usually need *both*.
- You added a new library and get a ClassNotFoundException at native runtime, but the app runs on the JVM. First diagnosis?The library (or your usage of it) lacks reachability metadata: it isn't in the repository, your version isn't covered, or a reflective path is uncovered. Check coverage, run the tracing agent, then add a RuntimeHintsRegistrar or exclude+override.
- What does @RegisterReflectionForBinding do that the repository doesn't?It declaratively registers your own DTO/type for reflective binding (serialization/validation) during Spring AOT — application-specific types the community repository can't know about.
- Do repository metadata and RuntimeHints ever conflict?No; they're additive and merge into one native-image config. If library metadata is actually wrong, you exclude that module and supply your own hints instead.
saying these in an interview costs you the question
- Claiming the repository makes RuntimeHints obsolete
- Thinking Spring can auto-infer hints for arbitrary third-party reflection
- Assuming 'runs on JVM' implies 'runs as native image'