Skip to content

absketches/codegen-svc-list-plugin

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

30 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Class Implementation Index Maven Plugin

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

Features

  • 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.

Requirements

  • Java 21
  • Maven 3.9.11

Quickstart

<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

Configuration properties (prefix: codegenConcreteClass.*)

Use dot-notation for class names in the configuration.

codegenConcreteClass.baseClasses (String) — required

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

codegenConcreteClass.usePrecompiled (boolean)

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

codegenConcreteClass.verbose (boolean)

Enable extra logging.

  • Default: false

codegenConcreteClass.generateReflectConfig (boolean)

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

codegenConcreteClass.reflectedClasses (String)

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

How it works

  1. Parses baseClasses and converts to JVM internal format.
  2. Scans your module’s class files and builds a header map.
  3. For each dependency JAR:
    • If usePrecompiled=true and a properties file exists at META-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.
  4. For each base type, the plugin unions precomputed + discovered implementations and writes the final properties file atomically.

Troubleshooting

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

  • baseClasses Has 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

Contract

  • 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.json without using the other feature by setting reflectedClasses and not configuring baseClasses.
  • both features can be used independently, and they also work together without conflict

About

Support projects to be GraalVM Native Image compatible

Resources

License

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages