更快 Maven 來襲,性能大幅提升!
相信作為Java開發(fā)者的你早已經(jīng)受夠了maven的編譯緩慢,但是又由于歷史包袱、使用習慣等問題暫時切換不了其他更快的構(gòu)建工具,這里筆者將給你介紹一款更快的maven——maven-mvnd。
1
maven-mvnd是Apache Maven團隊借鑒了Gradle和Takari后衍生出的更快的構(gòu)建工具。mvnd內(nèi)嵌了Maven,也正是因為這個原因我們可以無縫地將Maven切換為mvnd(也不需要單獨安裝Maven)。
在設(shè)計上,在mvnd中會生成一個或多個的守護進程來服務(wù)構(gòu)建請求以此來達到并行構(gòu)建的效果。另外在VM的選擇上,mvnd使用了GraalVM來代替?zhèn)鹘y(tǒng)的JVM,與之相比GraalVM啟動速度更快,占用的內(nèi)存更少。
根據(jù)文檔描述,與傳統(tǒng)的Maven相比mvnd具有以下優(yōu)勢:
運行構(gòu)建的JVM不需要為每個構(gòu)建重新啟動。
Maven插件類的類加載器緩存在多個構(gòu)建中,插件jars只會被讀取和解析一次。
JVM中JIT生成的本機代碼會被保留。與Maven相比,JIT編譯花費的時間更少。在重復構(gòu)建期間,JIT優(yōu)化的代碼立即可用。這不僅適用于來自Maven插件和Maven內(nèi)核的代碼,也適用于來自JDK本身的所有代碼。
默認情況下,mvnd使用多個CPU內(nèi)核并行構(gòu)建模塊。使用的內(nèi)核數(shù)由公式Math.max(Runtime.getRuntime().availableProcessors() - 1, 1)給出。如果您的源代碼樹不支持并行構(gòu)建,請在命令行上傳遞-T1以使您的構(gòu)建串行。
同時官方給出了24核機器上運行的動態(tài)圖:

2
對于mvnd的安裝,官方文檔給了十分詳細的教程,建議先行閱讀:https://github.com/apache/maven-mvnd 。
筆者是通過Homebrew進行安裝的,實踐證明macOS m1安裝使用是沒有問題的。不過需要注意的是通過此種方式安裝的mvnd版本為0.7.1,而經(jīng)過在ubuntu和macOS m1上進行測試發(fā)現(xiàn)此版本并不支持JDK8(可能僅是筆者電腦問題),而通過官方例子所示的JDK11確是沒問題。在JDK8運行mvnd命令會產(chǎn)生以下錯誤:
~ % 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)預估應(yīng)該是這種方式下載的執(zhí)行文件是通過高版本的JDK編譯的,在低版本上運行因為缺少某些方法或特性所以運行不了。在一籌莫展之際,筆者從maven-mvnd的最新版本的更新說明上發(fā)現(xiàn)一個Closed issues:Different java versions for mvnd and maven #512,在該問題上作者提供了一種解決方案就是將JAVA_HOME所指定的版本設(shè)置為JDK11,并且在運行mvnd命令時加上參數(shù)-Dmaven.compiler.release=8,即
mvnd -Dmaven.compiler.release=8?compile通過這種方式即能生成出JDK8所對應(yīng)的編譯代碼。
對于issue #512中作者回應(yīng)mvnd的最低支持版本是JDK8,但是筆者從0.5.2開始嘗試還是報同樣的錯...或許是筆者電腦存在一定的問題,因為我看到其他人在貼出的結(jié)果圖顯示JDK8下最新版本也是能夠安裝并使用的。另外如果還是不行的話也許我們能夠通過手動編譯源碼來生成可執(zhí)行文件,具體步驟在官方readme上已經(jīng)給出相應(yīng)的步驟。
3
?
在使用上與Maven的用法是完全相同的,只需將命令mvn改為mvnd即可。而在筆者本機的實測中,與傳統(tǒng)的Maven相比,通過mvnd的構(gòu)建所耗費的時間是原來的1/2。
4
?
本文筆者分別從maven-mvnd的介紹、安裝、使用及其出現(xiàn)的一些異常情況展開陳述,如果讀者想知道更多細節(jié)可閱讀官方文檔。而也許強化后的Maven依然比不過Gradle,但是在歷史包袱、使用習慣等背景下Maven的這次強化還是很香的。
參考:
https://github.com/apache/maven-mvnd
https://github.com/apache/maven-mvnd/issues/512
https://mp.weixin.qq.com/s/TG_6vq0mgbej8F3Qvpb6Vw
往期推薦
