A native image can omit a resource or reflective type that static analysis cannot see; RuntimeHints make that reachability explicit.
Spring native RuntimeHints: register resources reached only by name
Trace the missing access
A parcel printer loads a layout by a name assembled from a tenant configuration key. The JVM can find the resource on the classpath, while a native executable may omit it if no hint includes that path. Register the finite set of layouts through RuntimeHints. Treat arbitrary tenant-provided paths as untrusted input rather than adding a broad resource glob that packs secrets into the image.
Keep hints narrow
Spring AOT already discovers many framework serialization and configuration-property cases. Add custom hints for only the name-based access your code owns. For reflection, identify the exact type and members required instead of registering an entire package. A broad hint can enlarge the image and hide an architectural dependency that should be explicit. Build-time context decisions remain separate from reachability.
Test the real executable
A RuntimeHints unit test can assert that the declared path is registered, but only a native smoke test proves that the resource loads and the service performs its task. Delete or rename one resource in a negative test so a missing layout fails visibly rather than silently using a default.
Implementation sketch
class ParcelLayoutHints implements RuntimeHintsRegistrar {
@Override
public void registerHints(RuntimeHints hints, ClassLoader loader) {
hints.resources().registerPattern("parcel-layouts/standard.json");
hints.resources().registerPattern("parcel-layouts/oversize.json");
}
}Cost and verification
Each retained resource adds image size. Native smoke tests take longer than JVM tests, but they catch missing reachability metadata before production startup.
Common Mistakes
- Do not register every classpath resource to fix one missing layout.
- Do not use untrusted tenant text as a resource path.
- Do not call a RuntimeHints unit assertion a substitute for running the native executable.
Read next
Spring AOT: profile and conditional beans become build-time decisions, Spring ApplicationContextRunner: check conditional assembly in isolation, Spring Boot configuration validation: reject an unusable relay before work starts, Spring Boot configtree: bind one file per property in a child JVM.
