Gradle and Maven Plugins for Native Image with Initial JUnit 5 Testing Support
We are pleased to announce the release of the new official GraalVM Native Image Gradle and Maven plugins. The plugins aim to make GraalVM Native Image a first-class citizen in the JVM ecosystem: it makes building, testing, and running Java applications as native executables a breeze. The key new feature is the out-of-the-box support for native JUnit 5 testing.
The native JUnit support allows libraries in the JVM ecosystem to run their test suites via GraalVM Native Image. With integrated testing, library configuration should be always up to date and ready for the end user. We believe that this is the biggest step towards making the Java ecosystem native-ready.
Complete examples are available here.
Native Testing: The Way You Are Used to It
We’ve made it: testing Java code with JUnit 5 behaves exactly the same* in native execution as with the JVM. To make this work, we implemented a custom
junit-platform-native feature that logs tests that are discovered during the previous execution of the standard JVM
test task and registers them for native compilation and reflection. Based on this information, special test executable that contains all the tests (and their metadata) is built, and then invoked when using the corresponding build-tool task.
Collection of metadata imposes the dependency to the JVM
test task execution. The downside of this is increased testing time, but it also provides a suitable entry point for users to enable
native-image-agent invocation that can be used to generate missing reflection configuration for the project. Note that the agent invocation is independent from the test-metadata collection — the test metadata is always collected.
In the future we intend to work on removing the dependency on the JVM
testexecution. For this, we need modifications in the testing frameworks that will allow metadata collection without the execution of individual tests (a.k.a., dry-run support).
* Given proper configuration, and given that the project under test doesn’t include native-specific code (e.g., build-time initialization, substitutions, and plugins).
native-gradle-plugin to an existing Gradle project is as simple as including following to the
plugins section of the
as well as adding the following to the
After that, we can configure the image build by using a
nativeBuild configuration block:
The plugin then adds
nativeRun tasks that build and run the main class (as one might expect ☺). If the reflection configuration is necessary for the Native Image building, this plugin also provides a simple option that activates the
native-image-agent without any additional user setup. More information (and Kotlin configuration syntax) is available in the documentation.
To help ease the community transition, at the moment we support a subset of the configuration syntax and aliased task names from the most popular unofficial GraalVM Gradle plugins (
com.palantir.graal). Note that this behavior might eventually be deprecated.
Testing in Gradle
User can start Native Image testing by invoking the
nativeTest task (with the ability to add additional
native-image configuration using a
nativeTest configuration block).
Note that the native testing depends on running the standard
testtask in the JVM mode beforehand.
We are releasing our existing plugin under the new maven coordinates —
org.graalvm.buildtools:native-maven-plugin. This change was motivated by our intention to move faster with the plugin development by decoupling it from the GraalVM release cycle. Users of our existing
native-image-maven-plugin only need to change the plugin's
version in their
pom.xml, as the new plugin is backwards compatible with the old one. Versioning of the new plugin will start at
Adding our new plugin to the existing Maven project requires adding the following to the
After that, the user can build native images by running:
mvn -Pnative -DskipTests package
Testing in Maven
The user can start Native Image testing by running:
mvn -Pnative test
Maven plugin currently requires an extra step in order to enable said listener: The user needs to add a dependency to
org.graalvm.buildtools:junit-platform-native in their
pom.xml. This step will not be necessary once JUnit 5.8 lands.
Note that the native testing depends on running the standard test task in the JVM mode beforehand.
Documentation and more configuration options are available here.
The next step is creating a standardized repository with configuration that would be automatically added for legacy libraries. This should make the development for Native Image feels more frictionless even for libraries that don’t support it yet. We intend to follow up with patches and PRs for original libraries, working closely with the community in order to bring first party support to the most of the ecosystem.
Built with Love Through Collaboration
Our testing support was developed in collaboration with JUnit, Micronaut, and Spring teams. Many thanks to Sam Brannen, Graeme Rocher, and Sébastien Deleuze for their contributions and advice. Moving forward, our new plugins are already landing in Spring Native 0.10.0, and hopefully soon many more projects will follow.
We are looking forwards to hearing about your experiences and/or potential issues. Contributions are also very welcome.
The project repository is available at github.com/graalvm/native-build-tools.
All projects mentioned here are released under the Universal Permissive License.