相信作为
Java
开发者的你早已经受够了maven
的编译缓慢,但是又由于历史包袱、使用习惯等问题暂时切换不了其他更快的构建工具,这里笔者将给你介绍一款更快的maven
——maven-mvnd
。
介绍
maven-mvnd
是Apache Maven
团队借鉴了Gradle
和Takari
后衍生出的更快的构建工具。
架构
mvnd
内嵌了Maven
(因此不需要单独安装Maven
)。mvnd
客户端是通过GraalVM
构建的可执行文件,与启动传统JVM
相比,它的启动速度更快,占用的内存更少。- 实际构建发生在一个长期存在的后台进程(也称为守护进程)中。其中每个守护进程实例可以为
mvnd
客户端的多个连续请求提供服务。而如果没有空闲守护进程来服务构建请求,则可以并行生成多个守护进程。
优势
- 运行实际构建的
JVM
不需要为每个构建重新启动。 Maven
插件类的类加载器会缓存在多个构建中。因此,插件的jar
只被读取和解析一次(需要注意,SNAPSHOT
版本的Maven
插件不会被缓存的)。JVM
中即时编译器(JIT
)生成的本机代码会被保留。与Maven
相比,JIT
编译花费的时间更少。在重复构建期间,JIT
优化的代码立即可用。这不仅适用于来自Maven
插件和Maven
内核的代码,也适用于来自JDK
本身的所有代码。
功能
默认情况下,mvnd
使用多个CPU
内核并行构建模块,其中内核数由公式Math.max(Runtime.getRuntime().availableProcessors() - 1, 1)
得出。如果源代码树不支持并行构建,可在命令行上传递-T1
参数以使构建串行。
控制台输出的改进:因为在
Maven
上并行构建的输出是很难理解的,所以maven-mvnd
实现了一个简化的非滚动视图,在单独的行上显示每个构建线程的状态。
同时官方给出了24
核机器上运行的动态图:
安装
对于mvnd的安装,官方文档给了十分详细的教程,建议先行阅读:https://github.com/apache/maven-mvnd。
笔者是通过Homebrew
进行安装的,实践证明macOS m1
安装使用是没有问题的。不过需要注意的是通过此种方式安装的mvnd
版本为0.7.1
,而经过在ubuntu
和macOS m1
上进行测试发现此版本并不支持JDK8
(可能仅是笔者电脑问题),而通过官方例子所示的JDK11
确是没问题。在JDK8
运行mvnd
命令会产生以下错误:
~ % mvnd -v
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.UnsupportedClassVersionError: org/mvndaemon/mvnd/client/DefaultClient has been compiled by a more recent version of the Java Runtime (class file version 55.0), this version of the Java Runtime only recognizes class file versions up to 52.0
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:757)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:473)
at java.net.URLClassLoader.access$100(URLClassLoader.java:74)
at java.net.URLClassLoader$1.run(URLClassLoader.java:369)
at java.net.URLClassLoader$1.run(URLClassLoader.java:363)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:362)
at java.lang.ClassLoader.loadClass(ClassLoader.java:419)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352)
at java.lang.ClassLoader.loadClass(ClassLoader.java:352)
at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:601)
预估应该是这种方式下载的执行文件是通过高版本的JDK
编译的,在低版本上运行因为缺少某些方法或特性所以运行不了。在一筹莫展之际,笔者从maven-mvnd
的最新版本的更新说明上发现一个Closed issues:Different java versions for mvnd and maven #512
,在该问题上作者提供了一种解决方案就是将JAVA_HOME
所指定的版本设置为JDK11
,并且在运行mvnd
命令时加上参数-Dmaven.compiler.release=8
,即
mvnd -Dmaven.compiler.release=8 compile
通过这种方式即能生成出JDK8
所对应的编译代码。
对于
issue #512
中作者回应mvnd
的最低支持版本是JDK8
,但是笔者从0.5.2
开始尝试还是报同样的错…或许是笔者电脑存在一定的问题,因为我看到其他人在贴出的结果图显示JDK8
下最新版本也是能够安装并使用的。另外如果还是不行的话也许我们能够通过手动编译源码来生成可执行文件,具体步骤在官方readme
上已经给出相应的步骤。
使用
在使用上与Maven
的用法是完全相同的,只需将命令mvn
改为mvnd
即可。而在笔者本机的实测中,与传统的Maven
相比,通过mvnd
的构建所耗费的时间是原来的1/2
。
总结
本文笔者分别从maven-mvnd
的介绍、安装、使用及其出现的一些异常情况展开陈述,如果读者想知道更多细节可阅读官方文档。而也许强化后的Maven
依然比不过Gradle
,但是在历史包袱、使用习惯等背景下Maven
的这次强化还是很香的。
此外,对于本文的观点仅代表笔者个人,如有错误请各位大佬及时指出。
评论区