maven-mvnd
maven-mvnd copied to clipboard
Apache Maven Daemon
= mvnd
- the Maven Daemon
:toc: macro
image::https://img.shields.io/twitter/url/https/twitter.com/mvndaemon.svg?style=social&label=Follow%20%40mvndaemon[link="https://twitter.com/mvndaemon"]
toc::[]
== Introduction
This project aims at providing faster https://maven.apache.org/[Maven] builds using techniques known from Gradle and Takari.
Architecture overview:
-
mvnd
embeds 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
mvnd
client. - The
mvnd
client is a native executable built using https://www.graalvm.org/reference-manual/native-image/[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.
== Additional features
mvnd
brings the following features on top of the stock Maven:
- By default,
mvnd
is building your modules in parallel using multiple CPU cores. The number of utilized cores is given by the formulaMath.max(Runtime.getRuntime().availableProcessors() - 1, 1)
. If your source tree does not support parallel builds, pass-T1
on 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 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:
image::https://user-images.githubusercontent.com/1826249/103917178-94ee4500-510d-11eb-9abb-f52dae58a544.gif[] + Once the build is finished, the complete Maven output is forwarded to the console.
== How to install mvnd
=== Install using https://sdkman.io/[SDKMAN!]
If SDKMAN! supports your operating system, it is as easy as
[source,shell]
$ 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 JAVA_HOME
and
MVND_HOME
are managed by SDKMAN!.
=== Install using https://brew.sh/[Homebrew]
[source,shell]
$ brew install mvndaemon/homebrew-mvnd/mvnd
=== Install using https://www.macports.org[MacPorts]
[source,shell]
$ sudo port install mvnd
=== Install using https://community.chocolatey.org/packages/mvndaemon/[Chocolatey]
[source,shell]
$ choco install mvndaemon
=== Install using https://scoop.sh/[Scoop]
[source,shell]
$ scoop install mvndaemon
=== Install using https://github.com/joschi/asdf-mvnd#install[asdf]
[source,shell]
$ asdf plugin-add mvnd $ asdf install mvnd latest
=== Set up completion
Optionally, you can set up completion as follows: [source,shell]
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:
[source,shell]
$ unalias mvnd
=== Install manually
- Download the latest ZIP suitable for your platform from https://downloads.apache.org/maven/mvnd/
- Unzip to a directory of your choice
- Add the
bin
directory toPATH
- Optionally, you can create
~/.m2/mvnd.properties
and set thejava.home
property in case you do not want to bother with settingJAVA_HOME
environment variable. - Test whether
mvnd
works:
[source,shell]
$ 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.exe
from 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.
+
If you are on macOS, you'll need to remove the quarantine flags from all the files after unpacking the archive:
[source,shell]
$ xattr -r -d com.apple.quarantine mvnd-x.y.z-darwin-amd64
== Usage
mvnd
is designed to accept the same command line options like stock mvn
(plus some extras - see below), e.g.:
[source,shell]
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 --help
.
== Configuration Configuration can be provided through properties file. Mvnd read properties file from the following locations:
- the properties path supplied using
MVND_PROPERTIES_PATH
environment variable ormvnd.propertiesPath
system variable - the local properties path located at
[PROJECT_HOME]/.mvn/mvnd.properties
- the user properties path located at:
[USER_HOME]/.m2/mvnd.properties
- the system properties path located at:
[MVND_HOME]/conf/mvnd.properties
Properties defined in the first files will take precedence over properties specified in a lower ranked file.
A few special properties do not follow the above mechanism:
-
mvnd.daemonStorage
: this property defines the location where mvnd stores its files (registry and daemon logs). This property can only be defined as a system property on the command line -
mvnd.id
: this property is used internally to identify the daemon being created -
mvnd.extClasspath
: internal option to specify the maven extension classpath -
mvnd.coreExtensions
: internal option to specify the list of maven extension to register
For a full list of available properties please see https://github.com/apache/maven-mvnd/blob/master/dist/src/main/distro/conf/mvnd.properties[/dist/src/main/distro/conf/mvnd.properties].
== Build mvnd
from source
=== Prerequisites:
-
git
- Maven
- Download and unpack GraalVM CE from https://github.com/graalvm/graalvm-ce-builds/releases[GitHub]
- Set
JAVA_HOME
to where you unpacked GraalVM in the previous step. Check thatjava -version
output is as expected:
[source,shell]
$ $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)
- Install the
native-image
tool:
[source,shell]
$ $JAVA_HOME/bin/gu install native-image
-
native-image
may require additional software to be installed depending on your platform - see the https://www.graalvm.org/reference-manual/native-image/#prerequisites[native-image
documentation].
=== Build mvnd
[source,shell]
$ git clone https://github.com/apache/maven-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
=== Install mvnd
[source, shell]
$ cp -R dist/target/mvnd-[version] [target-dir]
Then you can simply add [target-dir]/bin
to your PATH
and run mvnd
.
We're happy to improve mvnd
, so https://github.com/apache/maven-mvnd/issues[feedback] is most welcome!