This plugin enables developers to make their applications GraalVM Native Image compatible. It automatically
generates the reflect-config.json file required by GraalVM to manage reflection in a controlled and predictable way,
improving startup performance and reducing binary size.
By limiting reflection to only the explicitly generated and necessary classes, the plugin ensures optimized runtime
behavior with minimal overhead.
This also generate a .properties index of all concrete implementations of one or more base types (abstract
classes) found in your project and its dependencies which are candidates for reflection.
It writes to:
META-INF/io/github/absketches/plugin/services.properties
Each key is a dotted base class; each value is a comma‑separated list of dotted implementation classes.
Example output:
org.nanonative.nano.core.model.Service=org.nanonative.devconsole.service.DevConsoleService,org.nanonative.nano.services.http.HttpServer
org.nanonative.nano.core.NanoServices=org.nanonative.nano.core.Nano- ⚡ Fast: Inspects only .class headers (no ASM, no classloading).
- 📦 Works across dependencies: Operates seamlessly across the current module and all resolved JARs.
- 🧹 Memoized Lookups: Caches discovered superclass chains in memory to eliminate redundant scans.
- 🔒 Zero intrusion: Requires no developer annotations or code changes - ideal for GraalVM native image workflows.
- Java 21
- Maven 3.9.11
<plugin>
<groupId>io.github.absketches</groupId>
<artifactId>codegen-concrete-classes-maven-plugin</artifactId>
<version>${codegen-mvn-plugin.version}</version>
<executions>
<execution>
<id>impl-index</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<baseClasses>org.nanonative.nano.core.model.Service,org.nanonative.nano.core.NanoServices</baseClasses>
<outputFile>services.properties</outputFile>
<usePrecompiledLists>true</usePrecompiledLists>
<verbose>true</verbose>
</configuration>
</execution>
</executions>
</plugin>Invoke:
mvn codegen-concrete-classes:generate
Use dot-notation for class names in the configuration.
Comma‑separated list of abstract base types (abstract classes) whose concrete implementations you want to index?
- Default: empty (must be provided)
- Example:
io.github.absketches.sentinel.Notification, org.nanonative.nano.core.model.Service
If true, when a dependency JAR already contains a properties file at the same location, i.e. *
*META-INF/io/github/absketches/plugin/**,
those entries are merged in. If a JAR’s precomputed file is missing some configured bases, that JAR is **scanned
** to fill gaps.
- Default:
true
Enable extra logging.
- Default:
false
Merges an existing reflect-config.json or creates a new one to enable native builds.
The generated reflect-config.json will appear under META-INF/native-image/<group>/<artifact>/ if not already
present.
- Default:
true
Comma-separated list of concrete classes that should be forced into the generated reflect-config.json.
The plugin will still create or merge reflect-config.json when this list is non-empty, even if no implementations were
found for the configured baseClasses.
- Default: empty
- Parses
baseClassesand converts to JVM internal format. - Scans your module’s class files and builds a header map.
- For each dependency JAR:
- If
usePrecompiled=trueand a properties file exists atMETA-INF/io/github/absketches/plugin/, it is read and filtered by your configured base types. - If the file is absent or does not include all the base types(incomplete), the JAR is scanned to populate headers.
- If
- For each base type, the plugin unions precomputed + discovered implementations and writes the final properties file atomically.
No services.properties in the JAR
- The plugin isn’t bound to that module?
- The module didn’t produce classes (empty sources or skipped compile)?
Empty services.properties
baseClassesHas baseClasses FQCN changed or does the module have any implementations at all?- Get verbose logging output using -DcodegenConcreteClass.verbose=true
Step-through debug Run this in the IDE of your project which includes this plugin:
mvnDebug process-classes
# Attach the debugger of the plugin project (this) to localhost:8000- must configure at least one base class to generate services metadata.
- Only concrete subclasses of configured super classes are listed.
- Scans compile + runtime classpath.
- reflect-config.json generation is enabled by default.
- can use it solely for generating
reflect-config.jsonwithout using the other feature by settingreflectedClassesand not configuringbaseClasses. - both features can be used independently, and they also work together without conflict