badge

Introduction

The Maven plugin for GraalVM Native Image building adds support for building and testing native images using Apache Maven™.

For upgrading please take a look at the Changelog.

Quickstart

You can find full samples in the source repository.

The plugin requires that you setup GraalVM and Native Image. The easiest way to install GraalVM with Native Image is to use the GraalVM JDK Downloader:

bash <(curl -sL https://get.graalvm.org/jdk)

It will then make use of Maven profiles to enable building and testing of native executables.

Reference documentation

Registering the plugin

Add the following profile to your pom.xml file to register the native-maven-plugin.

  <profiles>
    <profile>
      <id>native</id>
      <build>
        <plugins>
          <plugin>
            <groupId>org.graalvm.buildtools</groupId>
            <artifactId>native-maven-plugin</artifactId>
            <version>${native.maven.plugin.version}</version>
            <extensions>true</extensions>
            <executions>
              <execution>
                <id>build-native</id>
                <goals>
                  <goal>compile-no-fork</goal>
                </goals>
                <phase>package</phase>
              </execution>
              <execution>
                <id>test-native</id>
                <goals>
                  <goal>test</goal>
                </goals>
                <phase>test</phase>
              </execution>
            </executions>
            <configuration>
              <!-- ... -->
            </configuration>
          </plugin>
        </plugins>
      </build>
    </profile>
  </profiles>

You can then build a native executable directly with Maven using the mvn -Pnative -DskipTests package command without running the native-image command as a separate step.

The plugin figures out which JAR files it needs to pass to the native image and what the executable main class should be. If the heuristics fail with the no main manifest attribute, in target/<name>.jar error, the main class should be specified in the <configuration> node of the plugin. When mvn -Pnative package completes, an executable is ready for use, generated in the target directory of the project.

Building native image without attaching to the package phase can be done by invoking the forking compile goal directly, e.g. mvn native:compile
Testing pre-releases

You can use development versions of the plugin by adding our snapshot repository. Pre-releases are provided for convenience, without any guarantee.

<pluginRepositories>
    <pluginRepository>
        <id>graalvm-native-build-tools-snapshots</id>
        <name>GraalVM native-build-tools Snapshots</name>
        <url>https://raw.githubusercontent.com/graalvm/native-build-tools/snapshots</url>
        <releases>
            <enabled>false</enabled>
        </releases>
        <snapshots>
            <enabled>true</enabled>
        </snapshots>
    </pluginRepository>
</pluginRepositories>

Configuration options

If you use Native Image Maven plugin, it will pick up all the configuration for your application stored below the META-INF/native-image/ resource location, as described in Native Image Build Configuration. It is also possible to customize the plugin within a <configuration> node. The following configuration options are available.

<mainClass>

If the execution fails with the no main manifest attribute, in target/<name>.jar error, the main class should be specified. By default the plugin consults several locations in the pom.xml file in the following order to determine what the main class of the image should be.

  • <maven-shade-plugin> <transformers> <transformer> <mainClass>

  • <maven-assembly-plugin> <archive> <manifest> <mainClass>

  • <maven-jar-plugin> <archive> <manifest> <mainClass>

<imageName>

Use <imageName> to set a custom filename for the generated native image. If a custom image name is not supplied, the artifact ID of the project will be used by default.

<buildArgs>

If you want to pass additional arguments to the native image builder, use <buildArgs> in the configuration of the plugin:

<buildArgs>
    <arg>--argument</arg>
</buildArgs>
<skipNativeBuild>

To skip generation of the native image, supply the following in the configuration of the plugin:

<skipNativeBuild>true</skipNativeBuild>
<skipNativeTests>

To skip generation and execution of the native image compiled tests, supply the following in the configuration of the plugin:

<skipNativeTests>true</skipNativeTests>
<debug>

If you want to enable generation of debugging information supply the following in the configuration of the plugin:

<debug>true</debug>
<verbose>

If you want to enable verbose output during native-image building supply the following in the configuration of the plugin:

<verbose>true</verbose>
<sharedLibrary>

If you want to build image as a shared library supply the following in the configuration of the plugin:

<sharedLibrary>true</sharedLibrary>
<useArgFile>

If you want to use argument file for native-image building supply the following in the configuration of the plugin:

<useArgFile>true</useArgFile>
<quickBuild>

If you want to build the image using quick build mode, supply the following in the configuration of the plugin (alternatively set the GRAALVM_QUICK_BUILD environment variable to true):

<quickBuild>true</quickBuild>
<excludeConfig>

In order to exclude configuration from present jar files, specify:

<excludeConfig>
    <entry>
        <jarPath>dummy/path/to/file.jar</jarPath>
        <resourcePattern>*</resourcePattern>
    </entry>
</excludeConfig>
<environment>

To set environment options for native-image building supply the following in the configuration of the plugin:

<environment>
    <variable>value</variable>
</environment>
<systemPropertyVariables>

To specify system properties used for native-image building supply the following in the configuration of the plugin:

<systemPropertyVariables>
    <propertyName>value</propertyName>
</systemPropertyVariables>
<jvmArgs>

To specify JVM arguments used for native-image building supply the following in the configuration of the plugin:

<jvmArgs>
    <arg>argument1</arg>
    <arg>argument2</arg>
</jvmArgs>
<configurationFileDirectories>

If you want to specify custom directories where configuration files should be looked up, supply the following in the configuration of the plugin:

<configurationFileDirectories>
    <dir>path/to/dir</dir>
</configurationFileDirectories>
<classpath>

Sets a custom classpath instead of plugin generated one. Usage:

<classpath>
    <entry>path/to/file.jar</entry>
    <entry>path/to/classes</entry>
</classpath>
<classesDirectory>

If you want to specify custom path to packed JAR, or a custom directory that contains only application classes, but want the plugin to still automatically add classpath entries for dependencies, simply add:

<classesDirectory>
    path/to/dir
</classesDirectory>
<agent>

Configuration of the native agent. See Enabling the agent and Configuring agent options for details.

For example, to build a native image named executable-name that uses org.example.ClassName as its main class with assertions enabled, add the following <configuration> block for the native-maven-plugin.

<configuration>
  <imageName>executable-name</imageName>
  <mainClass>org.example.ClassName</mainClass>
  <fallback>false</fallback>
  <verbose>true</verbose>
</configuration>
<requiredVersion>

If you want to define the minimum GraalVM version, can be MAJOR, MAJOR.MINOR or MAJOR.MINOR.PATCH:

<requiredVersion>22.3</requiredVersion>
Most of the aforementioned properties can also be set from command line as a part of Maven invocation — for example if you want to temporarily enable verbose mode you can append -Dverbose to your Maven invocation.
If you use GraalVM Enterprise as the JAVA_HOME environment, the plugin builds a native image with enterprise features enabled — for example, an executable will automatically be built with compressed references and other optimizations enabled.

Reusing configuration from a parent POM

The <buildArgs> element can be combined between parent and children POMs. Suppose you have the following parent POM definition:

<plugin>
  <groupId>org.graalvm.buildtools</groupId>
  <artifactId>native-maven-plugin</artifactId>
  <version>${current_plugin_version}</version>
  <configuration>
    <imageName>${project.artifactId}</imageName>
    <mainClass>${exec.mainClass}</mainClass>
    <buildArgs>
      <buildArg>--no-fallback</buildArg>
    </buildArgs>
  </configuration>
</plugin>

Children projects have the ability to append <buildArg> arguments in the following way:

<plugin>
  <groupId>org.graalvm.buildtools</groupId>
  <artifactId>native-maven-plugin</artifactId>
  <configuration>
    <buildArgs combine.children="append">
      <buildArg>--verbose</buildArg>
    </buildArgs>
  </configuration>
</plugin>

In this case, the arguments that will be passed to the native-image executable will be:

--no-fallback --verbose

Testing support

This plugin supports running tests on the JUnit Platform as native images. This means that tests will be compiled and executed as native code.

The minimum supported version is JUnit 5.8.1 (JUnit Platform 1.8.1, JUnit Jupiter 5.8.1, JUnit Vintage 5.8.1)

In theory, any TestEngine supported on the JUnit Platform should be supported by this plugin as long as the programming language used by the TestEngine and the programming language used to write the tests is supported in a GraalVM native image. This plugin provides explicit support for the JUnit Jupiter and JUnit Vintage test engines, and support for additional test engines should be possible with custom native configuration.

In order to use the recommended JUnit Platform test listener mode, you need to enable extensions for the native-maven-plugin by adding <extensions>true</extensions> as follows.

<plugin>
    <groupId>org.graalvm.buildtools</groupId>
    <artifactId>native-maven-plugin</artifactId>
    <version>${native.maven.plugin.version}</version>
    <extensions>true</extensions>

Running mvn -Pnative test will then build and run native tests.

Version compatibility

This plugin requires Maven Surefire 2.22.0 or higher to run tests within a native image.

Each version of the Maven Surefire plugin has a dependency on a particular version of the JUnit Platform. You therefore need to ensure that Maven Surefire is using at least version 1.8 of the JUnit Platform. Beginning with version 3.0 M4, Maven Surefire will automatically align the JUnit Platform version used by Surefire with the version needed by the user’s configured version of JUnit Jupiter or JUnit Vintage. Since the examples in this document use Maven Surefire 3.0 M5, their maven POMs do not require any special configuration regarding the JUnit Platform version. However, if you are using a version of Maven Surefire prior to 3.0 M4 you will need to add an explicit dependency on the junit-platform-launcher artifact to the dependencies section of your native profile configuration as in the following example.

<dependencies>
	<dependency>
		<groupId>org.junit.platform</groupId>
		<artifactId>junit-platform-launcher</artifactId>
		<version>1.8.2</version>
		<scope>test</scope>
	</dependency>
</dependencies>
If you have imported the junit BOM or are using a plugin that manages JUnit versions for you — for example, Spring Boot — you may want to omit the <version> configuration in the above example.

If Maven Surefire is using an older version of the JUnit Platform, the build will fail with an error similar to the following when attempting to run tests in a native image.

[ERROR] Test configuration file wasn't found. Make sure that test execution wasn't skipped.

Disabling testing support

If you wish to disable tests on the JVM as well as tests within a native image, you can invoke Maven with the -DskipTests flag. This flag is supported by Maven Surefire and Native Build Tools. Several examples in Running your application with the agent demonstrate the use of this flag.

If you wish to run tests on the JVM with Maven Surefire but skip testing within a native image, you can invoke Maven with the -DskipNativeTests flag. This flag is specific to Native Build Tools. For example, you might wish to disable only native testing support for use cases such as the following:

  • You don’t actually want to run your tests in native mode.

  • Your library or application uses a testing framework that is not supported on the JUnit Platform.

  • You need to use the agent when running tests on the JVM but do not wish to run those same tests in native mode.

Long classpath, @argument file and shading support

Under Windows, it is possible that the length of the classpath exceeds what the operating system supports when invoking the CLI to build a native image.

To avoid this, since release 0.9.10, the plugin will use an argument file to pass the arguments to the native-image tool, instead of passing them directly.

In case you are using a GraalVM version older than 21.3, you will however have to use a workaround, since the argument file wasn’t supported.

One option is to use a shaded jar and use it instead of individual jars on classpath.

First, you’ll need to setup the Maven Shade plugin:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version>3.2.4</version>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>shade</goal>
            </goals>
            <configuration>
                <shadedArtifactAttached>true</shadedArtifactAttached>
            </configuration>
        </execution>
    </executions>
</plugin>

If you need testing support, add the JUnit Platform Native dependency explicitly:

<dependencies>
    <dependency>
        <groupId>org.graalvm.buildtools</groupId>
        <artifactId>junit-platform-native</artifactId>
        <version>${junit.platform.native.version}</version>
        <scope>test</scope>
    </dependency>
</dependencies>

Then the native plugin needs to be configured to use this jar instead of the full classpath:

<plugin>
    <groupId>org.graalvm.buildtools</groupId>
    <artifactId>native-maven-plugin</artifactId>
    <version>${native.maven.plugin.version}</version>
    <extensions>true</extensions>
    <executions>
        <execution>
            <id>build-native</id>
            <goals>
                <goal>compile-no-fork</goal>
            </goals>
            <phase>package</phase>
        </execution>
    </executions>
    <configuration>
        <skip>false</skip>
        <useArgFile>false</useArgFile>
        <imageName>${imageName}</imageName>
        <fallback>false</fallback>
        <classpath>
            <param>${project.build.directory}/${project.artifactId}-${project.version}-shaded.jar</param>
        </classpath>
    </configuration>
</plugin>

Depending on the other plugins your build uses (typically the Spring Boot plugin), you might have to configure, in addition, the main class:

<plugin>
    <groupId>org.graalvm.buildtools</groupId>
	<artifactId>native-maven-plugin</artifactId>
	<version>${native.buildtools.version}</version>
	<configuration>
		<imageName>${project.artifactId}</imageName>
		<mainClass>${exec.mainClass}</mainClass>
		<buildArgs>
			<buildArg>--no-fallback</buildArg>
		</buildArgs>
		<classpath>
			<param>
				${project.build.directory}/${project.artifactId}-${project.version}-shaded.jar
			</param>
		</classpath>
...

To be able to execute tests in native mode, you will need more setup:

  • Create a src/assembly/test-jar-with-dependencies.xml file with the following contents:

<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
    <id>tests</id>
    <formats>
        <format>jar</format>
    </formats>
    <fileSets>
        <fileSet>
            <directory>${project.build.directory}/test-classes</directory>
            <outputDirectory>/</outputDirectory>
        </fileSet>
        <fileSet>
            <directory>${project.build.outputDirectory}</directory>
            <outputDirectory>/</outputDirectory>
        </fileSet>
    </fileSets>
    <includeBaseDirectory>false</includeBaseDirectory>
    <dependencySets>
        <dependencySet>
            <outputDirectory>/</outputDirectory>
            <useProjectArtifact>true</useProjectArtifact>
            <unpack>true</unpack>
            <scope>test</scope>
        </dependencySet>
    </dependencySets>
</assembly>
  • Add the assembly plugin to your native profile:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-assembly-plugin</artifactId>
    <version>2.4.1</version>
    <configuration>
        <descriptors>
            <descriptor>src/assembly/test-jar-with-dependencies.xml</descriptor>
        </descriptors>
    </configuration>
    <executions>
        <execution>
            <id>make-test-jar</id>
            <phase>package</phase>
            <goals>
                <goal>single</goal>
            </goals>
        </execution>
    </executions>
</plugin>
  • Due to a limitation in Maven, you will need to move the tests execution to the "integration-test" phase:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>3.0.0-M5</version>
</plugin>
<plugin>
    <groupId>org.graalvm.buildtools</groupId>
    <artifactId>native-maven-plugin</artifactId>
    <version>${native.maven.plugin.version}</version>
    <extensions>true</extensions>
    <executions>
        <execution>
            <id>test-native</id>
            <goals>
                <goal>test</goal>
            </goals>
            <phase>integration-test</phase>
            <configuration>
                <classpath>
                    <param>${project.build.directory}/${project.artifactId}-${project.version}-tests.jar</param>
                </classpath>
            </configuration>
        </execution>
        <execution>
            <id>build-native</id>
            <goals>
                <goal>compile-no-fork</goal>
            </goals>
            <phase>package</phase>
            <configuration>
                <classpath>
                    <param>${project.build.directory}/${project.artifactId}-${project.version}-shaded.jar</param>
                </classpath>
            </configuration>
        </execution>
    </executions>
    <configuration>
        <skip>false</skip>
        <useArgFile>false</useArgFile>
        <imageName>${imageName}</imageName>
        <fallback>false</fallback>
    </configuration>
</plugin>

Finally, you will need to execute tests using the integration-test phase instead of test:

./mvn -Pnative integration-test

Please refer to the Maven Shade plugin documentation for more details on how to configure shading and the Maven Assembly plugin documentation to tweak what to include in tests.

Reflection support and running with the native agent

If your project requires reflection, classpath resources, dynamic proxies or other features requiring explicit native configuration, it may prove helpful to first run your application or tests using the native-image-agent.

The Native Image Maven plugin simplifies generation of the required configuration files by injecting the agent automatically for you (this includes, but is not limited to the reflection file).

The agent generates the native configuration files in subdirectories of target/native/agent-output. Although those files will be automatically used if you run your build with the agent enabled, you should consider reviewing the generated files and adding them to your sources instead.

Enabling the agent

The agent is disabled by default, but it can be enabled within your pom.xml file or via the command line.

To enable the agent by default, specify <enabled>true</enabled> as follows in the configuration of the native-maven-plugin in your POM.

<configuration>
  <agent>
    <enabled>true</enabled>
  </agent>
</configuration>

To enable the agent via the command line, supply the -Dagent=true flag when running Maven. The examples in the following sections demonstrate how to do this for your application and for tests.

If you have enabled the agent within your POM, you can still disable it via the command line by supplying the -Dagent=false flag.

Configuring agent options

If you would like to configure the options for the agent — for example, to configure agent mode or advanced features such as Caller-based Filters and Access Filters - you can specify them in your POM as described bellow.

<configuration>
    <agent>
        <enabled>true</enabled>
        <defaultMode>Standard</defaultMode>
        <modes>
            <direct>config-output-dir=${project.build.directory}/native/agent-output</direct>
            <conditional>
                <userCodeFilterPath>user-code-filter.json</userCodeFilterPath>
                <extraFilterPath>extra-filter.json</extraFilterPath>
                <parallel>true</parallel>
            </conditional>
        </modes>
        <options>
            <callerFilterFiles>
                <filterFile>caller-filter-file1.json</filterFile>
                <filterFile>caller-filter-file2.json</filterFile>
            </callerFilterFiles>
            <accessFilterFiles>
                <filterFile>access-filter-file1.json</filterFile>
                <filterFile>access-filter-file2.json</filterFile>
            </accessFilterFiles>
            <builtinCallerFilter>true</builtinCallerFilter>
            <builtinHeuristicFilter>true</builtinHeuristicFilter>
            <enableExperimentalPredefinedClasses>true</enableExperimentalPredefinedClasses>
            <enableExperimentalUnsafeAllocationTracing>
                true
            </enableExperimentalUnsafeAllocationTracing>
            <trackReflectionMetadata>true</trackReflectionMetadata>
        </options>
        <metadataCopy>
            <!-- you can specify metadataCopy configuration here -->
        </metadataCopy>
    </agent>
</configuration>

This example shows all possibilities you can use for native agent configuration. If you don’t need some of the options, just remove them.

Agent can be run in one of the following modes:

  • standard - in this mode you run agent only with options provided in options section.

  • direct - in this mode you can provide command line that you want to be executed as an agent configuration. In this mode, user is fully responsible for agent configuration, and the rest of the agent configuration, provided in pom.xml file, will be ignored.

  • conditional - in this mode you can provide additional files that can be used as a filter for the agent output. You can read more about conditional mode here.

Each option and how you should use it is described bellow:

  • enabled - a simple flag that specifies whether the agent is enabled or not. Can be set to true or false.

  • defaultMode - agent mode switcher. Can be set to: standard, direct or conditional.

  • modes - list of additional mode options, specific for certain mode type. Inside this tag, you can specify options for direct or conditional modes. Standard mode doesn’t have any specific options.

    • in case of direct mode you can specify <direct> tag, with the agent command line as its value

    • in case of conditional mode you can specify <conditional> tag, and set additional filter files inside <userCodeFilterPath> and <extraCodeFilterPath>. Also, you can set value for <parallel> tag. If the value is true, agent will create partial-config file, and merge it with conditional merge, otherwise agent will generate same kind of output as other modes.

  • options - list of options that can be specify independent from agent mode. More about common options can be found here.

Metadata copy

metadataCopy provides additional options for manipulating the agent output after agent finishes its job.

<metadataCopy>
    <disabledStages>
        <stage>main</stage>
    </disabledStages>
    <merge>true</merge>
    <outputDirectory>/tmp/test-output-dir</outputDirectory>
</metadataCopy>

You can set values for the following tags:

  • <outputDirectory> - where you want to copy agent output.

  • <merge> - in case you already have some other config files inside output directory, you can choose whether you want to override those files or merge new files with the existing once (set merge value to true).

  • <disabledStages> - in case you don’t want to copy output of the certain stage (main or test) you can disable them and metadataCopy will not look at the agent output for that stage. For example, if you want to copy only config files generated in tests, you can disable main stage. Also, if you want to copy only files generated in main phase, you can disable test stage. Therefore, if you skip both stages, metadataCopy will not be executed.

Running tests with the agent

The simplest way to use the agent is to do it via execution of your tests.

Run your test suite with:

mvn -Pnative -Dagent=true test

When the agent system property is set to true (or when the agent is enabled in the POM), the agent will be automatically attached to your Maven Surefire test execution, and the generated files can be found in the target/native/agent-output/test directory.

If you want to run metadataCopy as well, first define its configuration as described above and add native:metadata-copy at the end of the agent invocation command. Example:

mvn -Pnative -Dagent=true test native:metadata-copy

Running your application with the agent

Executing your application with the agent is more involved and requires you to configure a separate mojo execution which allows forking the Java process.

In your native Maven profile section, add the following:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>exec-maven-plugin</artifactId>
    <version>3.0.0</version>
    <executions>
        <execution>
            <id>java-agent</id>
            <goals>
                <goal>exec</goal>
            </goals>
            <phase>test</phase>
            <configuration>
                <executable>java</executable>
                <workingDirectory>${project.build.directory}</workingDirectory>
                <arguments>
                    <argument>-classpath</argument>
                    <classpath/>
                    <argument>${mainClass}</argument>
                </arguments>
            </configuration>
        </execution>
    </executions>
</plugin>
<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>exec-maven-plugin</artifactId>
    <version>3.0.0</version>
    <executions>
        <execution>
            <id>java-agent</id>
            <goals>
                <goal>exec</goal>
            </goals>
            <phase>test</phase>
            <configuration>
                <executable>java</executable>
                <workingDirectory>${project.build.directory}</workingDirectory>
                <arguments>
                    <argument>-classpath</argument>
                    <classpath/>
                    <argument>${mainClass}</argument>
                </arguments>
            </configuration>
        </execution>
    </executions>
</plugin>

Then you can execute your application with the agent by running:

mvn -Pnative -Dagent=true -DskipTests -DskipNativeBuild=true package exec:exec@java-agent

Both of the above commands will generate configuration files in the target/native/agent-output/main directory. If you want to run your native application with those configuration files, you then need to execute the following command:

mvn -Pnative -Dagent=true -DskipTests package exec:exec@native

GraalVM Reachability Metadata Support

Since release 0.9.12, the plugin adds support for the GraalVM reachability metadata repository. This repository provides reachability metadata for libraries that do not support GraalVM Native Image.

This version of the plugin defaults to the using the metadata repository in version 0.2.6. There is nothing for you to configure if you are fine with this version. The repository is also published on Maven Central at the following coordinates:

<dependency>
   <groupId>org.graalvm.buildtools</groupId>
    <artifactId>graalvm-reachability-metadata</artifactId>
    <version>{maven-plugin-version}</version>
    <classifier>repository</classifier>
    <type>zip</type>
</dependency>

e.g. graalvm-reachability-metadata-0.9.20-repository.zip.

Enabling the metadata repository

Support needs to be enabled explicitly by including the following into the <configuration> element:

Enabling the metadata repository
<metadataRepository>
    <enabled>true</enabled>
</metadataRepository>

Alternatively, you can use a remote repository, in which case you can specify the URL of the ZIP file:

Enabling a remote repository
<metadataRepository>
    <enabled>true</enabled>
    <url>${metadata.url}</url>
</metadataRepository>

For debugging purposes you can use a local repository:

Enabling a local repository
<metadataRepository>
    <enabled>true</enabled>
    <localPath>${project.basedir}/config-directory</localPath> (1)
</metadataRepository>
1 The local path can point to an exploded directory, or to a compressed ZIP file.

Configuring the metadata repository

Once activated, for each library included in the native image, the plugin will automatically search for GraalVM reachability metadata in the repository that was released together with the plugin. In case you want to use another verion of the metadata use:

Choosing a version for the metadata repository
<metadataRepository>
    <enabled>true</enabled>
    <version>0.2.3</version>
</metadataRepository>

In some cases, you may need to exclude a particular module from the search. This can be done by configuring that particular dependency:

Excluding a module from search
<metadataRepository>
    <enabled>true</enabled>
    <localPath>${project.basedir}/config-directory</localPath>
    <dependencies>
        <dependency>
            <groupId>org.graalvm.internal</groupId>
            <artifactId>library-with-reflection</artifactId>
            <excluded>true</excluded>
        </dependency>
    </dependencies>
</metadataRepository>

Last, it is possible for you to override the metadata version of a particular module. This may be interesting if there’s no specific metadata available for the particular version of the library that you use, but that you know that a version works:

Specifying the metadata version to use for a particular library
<metadataRepository>
    <enabled>true</enabled>
    <localPath>${project.basedir}/config-directory</localPath>
    <dependencies>
        <dependency>
            <groupId>org.graalvm.internal</groupId>
            <artifactId>library-with-reflection</artifactId>
            <metadataVersion>2</metadataVersion>
        </dependency>
    </dependencies>
</metadataRepository>

Adding metadata respoistory files

By default, repository metadata will be used only when your native image is generated. In some situations, you may want to include the metadata directly inside your jar.

Adding metadata to your jar can be useful when some other process is responsible for converting your jar into a native image. For example, you might be generating a shaded jar and using a Paketo buildpack to convert it to a native image.

To include metadata repository inside your jar you can use the add-reachability-metadata goal. Typically the goal will be included in an execution step where by default it will be bound to the generate-resources phase:

Configuring the add-reachability-metadata goal to execute with the generate-resources phase
<executions>
    <execution>
        <id>add-reachability-metadata</id>
        <goals>
            <goal>add-reachability-metadata</goal>
        </goals>
    </execution>
</executions>

Javadocs

In addition, you can consult the Javadocs of the plugin.