Native Maven

Run Maven builds through a natively compiled Maven with elide mvn

Native Maven is experimental and very early in development. Expect gaps, rough edges, and changes to flags and behavior between releases. Keep a regular Maven installation available for builds that must not break.

Native Maven is Apache Maven 4 compiled to a native executable with GraalVM Native Image. It starts in milliseconds instead of seconds and can run typical pom.xml builds about twice as fast as Maven on a JVM. Elide drives it through the elide mvn command, so no separate Maven or JDK installation is needed.

Run a build

Everything after -- is passed to Maven unchanged:

elide mvn -- package
elide mvn -- -f app/pom.xml clean install
elide mvn -- --version

The multi-module project root is located the same way Maven’s launcher does it: from the -f/--file directory (or the working directory), walking up to the nearest .mvn marker.

First run

The Elide distribution ships no Native Maven images, which keeps the download small. On first use, elide mvn asks to download the image it needs:

Native Maven component 'generic' is not installed. Download it now? [Y/n]

Answer yes once. Images install under lib/maven/bin/ inside the Elide home directory and are reused on every later run. Non-interactive sessions, such as CI, approve the download automatically.

Pass --yes after -- to approve every download without a prompt, even when a terminal is attached. This suits CI runners that allocate a TTY, and any script that must not block on input:

elide mvn -- --yes package

Published images exist for these platforms:

PlatformArchitecture
Linuxx86_64, aarch64
macOSaarch64
Windowsx86_64

Flavors

A native image cannot load arbitrary classes at run time, so a set of Maven plugins is compiled into each image. That set is called a flavor. Plugins inside the flavor run at native speed; anything else depends on the mode below.

FlavorBaked pluginsBest for
genericMaven’s default lifecycle: clean, resources, compiler, surefire, jar, install, deployPlain Java or Kotlin projects with no build plugins
spring@4.1.0Everything a Spring Initializr project on Spring Boot 4.1 usesSpring Boot 4.1.x
spring@4.0.7Same, for Spring Boot 4.0Spring Boot 4.0.x

Elide selects the flavor automatically. It reads the project’s pom.xml for a Spring Boot version, taken from a spring-boot-starter-parent parent or an explicit spring-boot-maven-plugin version, and picks the published image on the same major.minor line. A Boot 4.1.3 project therefore uses spring@4.1.0. Projects without a detectable Boot version use generic.

Version placeholders such as ${spring.version} are not resolved and fall back to generic. Request a flavor explicitly when detection does not match your project:

elide mvn -- --flavor spring@4.1.0 package
elide mvn -- --flavor=spring@4.0.7 -f app/pom.xml install

--flavor is an Elide option and is removed before the arguments reach Maven. It may appear anywhere after --. Each flavor is a separate download that installs on first use, the same way as the generic image.

Modes

Mode decides what happens when a build needs a plugin that is not baked into the selected flavor. Set it with --mode=<value> after --:

elide mvn -- --mode=mixed package
ModeBehavior
native (default)Only baked plugins run. A missing plugin fails the build early with an error that names the flavor most likely to contain it and suggests --mode=mixed. Fastest start and run.
mixedBaked plugins run natively. Every other goal runs, one at a time, on a HotSpot JVM booted inside the same process. The best balance of speed and compatibility.
legacyThe whole build runs on the in-process HotSpot JVM as plain Apache Maven. No speedup; useful as a baseline to compare the other modes against.

Only the --mode=value form is recognized. The -Dnmvn.mode=<value> system property works too; an explicit flag wins over it.

mixed and legacy need a Maven distribution to boot the JVM from. On first use of either mode, elide mvn asks to download it into lib/maven/ next to the images. This is Native Maven’s own distribution, which carries the in-process bridge that stock Apache Maven lacks. Elide itself serves as the JVM; no separate JDK is required.

Mixed mode limits

Each delegated goal is a fresh Maven invocation inside the shared JVM, which adds roughly 0.2 seconds per goal after a one-time boot. A build that delegates most of its goals still works but no longer runs at native speed; pick a closer flavor instead.

Artifacts produced by a delegated goal are not attached to the native session. If the packaging plugin is not baked, run package rather than install or deploy, because the baked install goal cannot see a jar that a delegated jar:jar wrote. Plugin configuration given on the command line crosses the boundary only as -D user properties.

Compilation

Native Maven images include the Java compiler and compile in-process. A plugin configured to fork the compiler resolves javac from the Elide installation, so forked builds work without any other JDK on the machine.

Output

In an interactive terminal, elide mvn shows a live status line with the running plugin, goal, version, and module, then prints a summary of completed phases and the total build time. On failure it prints the full Maven log.

Pass --porcelain after -- to stream Maven’s own output instead. Verbose and debug runs, and non-interactive sessions, stream it automatically:

elide mvn -- --porcelain package

Inspect an installed image

Each image can describe itself. Run the binary directly from the Elide home directory, with --info as its first argument:

<elide-home>/lib/maven/bin/nmvn-generic --info
<elide-home>/lib/maven/bin/nmvn-spring-4.1.0 --info=plugins

--info prints the flavor, the variant, and every baked plugin. Passing --info=plugins, --info=flavor, or --info=variant prints just that value, which suits scripts.

Compatibility

Native Maven aims to become a drop-in replacement. It reads the same pom.xml, runs the same plugins, and follows the same lifecycle as Apache Maven 4, but plugin coverage is still limited to the published flavors and compatibility is not yet complete. --flavor and --mode are opt-ins layered on top and are meant to stay usable across future releases.

  • Maven Dependencies installs Maven coordinates declared in elide.pkl without running a Maven build.
  • Dependencies covers install flags and the on-disk layout.
  • JVM Toolchain lists the compiler, formatter, and packaging commands.