mvnd - the Maven Daemon
This project aims at providing faster Maven builds using techniques known from Gradle and Takari.
mvndembeds Maven (so there is no need to install Maven separately).
The actual builds happen inside a long living background process, a.k.a. daemon.
One daemon instance can serve multiple consecutive requests from the
mvndclient is a native executable built using GraalVM. It starts faster and uses less memory compared to starting a traditional JVM.
Multiple daemons can be spawned in parallel if there is no idle daemon to serve a build request.
This architecture brings the following advantages:
The JVM for running the actual builds does not need to get started anew for each build.
The classloaders holding classes of Maven plugins are cached over multiple builds. The plugin jars are thus read and parsed just once. SNAPSHOT versions of Maven plugins are not cached.
The native code produced by the Just-In-Time (JIT) compiler inside the JVM is kept too. Compared to stock Maven, less time is spent by the JIT compilation. During the repeated builds the JIT-optimized code is available immediately. This applies not only to the code coming from Maven plugins and Maven Core, but also to all code coming from the JDK itself.
mvnd brings the following features on top of the stock Maven:
mvndis building your modules in parallel using multiple CPU cores. The number of utilized cores is given by the formula
Math.max(Runtime.getRuntime().availableProcessors() - 1, 1). If your source tree does not support parallel builds, pass
-T1on the command line to make your build serial.
Improved console output: we believe that the output of a parallel build on a stock Maven is hard to follow. Therefore, we implemented a simplified a non-rolling view showing the status of each build thread on a separate line. This is what it looks like on a machine with 24 cores:
Once the build is finshed, the complete Maven output is forwarded to the console.
How to install
If SDKMAN! supports your operating system, it is as easy as
$ sdk install mvnd
If you used the manual install in the past, please make sure that the settings in
~/.m2/mvnd.properties still make
sense. With SDKMAN!, the
~/.m2/mvnd.properties file is typically not needed at all, because both
MVND_HOME are managed by SDKMAN!.
$ brew install mvndaemon/homebrew-mvnd/mvnd
Set up completion
Optionally, you can set up completion as follows:
# ensure to set MVND_HOME to point to your mvnd distribution, note that sdkman does it for you $ echo 'source $MVND_HOME/bin/mvnd-bash-completion.bash' >> ~/.bashrc
bash is the only shell supported at this time.
Note for oh-my-zsh users
Users that use
oh-my-zsh often use completion for maven. The default maven completion plugin defines
mvnd as an alias to
mvn deploy. So before being able to use
mvnd, you need to unalias using the following command:
$ unalias mvnd
Download the latest ZIP suitable for your platform from https://github.com/mvndaemon/mvnd/releases
Unzip to a directory of your choice
Optionally, you can create
~/.m2/mvnd.propertiesand set the
java.homeproperty in case you do not want to bother with setting
$ mvnd --version Maven Daemon 0.0.11-linux-amd64 (native) Terminal: org.jline.terminal.impl.PosixSysTerminal with pty org.jline.terminal.impl.jansi.osx.OsXNativePty Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f) Maven home: /home/ppalaga/orgs/mvnd/mvnd/daemon/target/maven-distro Java version: 11.0.1, vendor: AdoptOpenJDK, runtime: /home/data/jvm/adopt-openjdk/jdk-11.0.1+13 Default locale: en_IE, platform encoding: UTF-8 OS name: "linux", version: "5.6.13-200.fc31.x86_64", arch: "amd64", family: "unix"
If you are on Windows and see a message that
VCRUNTIME140.dll was not found, you need to install
vc_redist.x64.exefrom https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads. See https://github.com/oracle/graal/issues/1762 for more information.
mvnd is designed to accept the same command line options like stock
mvn (plus some extras - see below), e.g.:
mvnd clean install
mvnd specific options
--status lists running daemons
--stop kills all running daemons
The complete list of options is printed when executing
mvnd from source
Download and unpack GraalVM CE from GitHub
JAVA_HOMEto where you unpacked GraalVM in the previous step. Check that
java -versionoutput is as expected:
$ $JAVA_HOME/bin/java -version openjdk version "11.0.9" 2020-10-20 OpenJDK Runtime Environment GraalVM CE 20.3.0 (build 11.0.9+10-jvmci-20.3-b06) OpenJDK 64-Bit Server VM GraalVM CE 20.3.0 (build 11.0.9+10-jvmci-20.3-b06, mixed mode, sharing)
$ $JAVA_HOME/bin/gu install native-image
native-imagemay require additional software to be installed depending on your platform - see the
$ git clone https://github.com/mvndaemon/mvnd.git $ cd mvnd $ mvn clean verify -Pnative ... $ cd client $ file target/mvnd target/mvnd: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=93a554f3807550a13c986d2af9a311ef299bdc5a, for GNU/Linux 3.2.0, with debug_info, not stripped $ ls -lh target/mvnd -rwxrwxr-x. 1 ppalaga ppalaga 25M Jun 2 13:23 target/mvnd
Known issues and limitations
Parallel build, hence
mvnd, don’t play well with
-rfmaven option at the monet. If you use the
-rfmaven option with
mvndyou have no guarantee that all the modules will have been built (There are some improvements planned on this in the next
We’re happy to improve
mvnd, so feedback is most welcomed!