編譯spring boot 3 native + jpa的原生鏡像
其中涉及版本:
maven: 3.5.4
jdk: 17
graalvm: 22.3
springboot + jpa: 3.0.8
一、Windows
1、graalvm安裝

解壓到任意目錄后添加JAVA_HOME環(huán)境變量

新增path:%JAVA_HOME%與%JAVA_HOME%\bin
安裝成功:

2、安裝VisualStudio
必須的選擇:
MSVC v143 - VS 2022 c++ x64/x86生成工具 根據(jù)你的jdk版本來選,jdk11需要MSVC v140 2015、jdk15需要MSVC v141 2017、jdk17需要MSVC v142 2019、jdk21需要MSVC v143 2022。當(dāng)然他們向下兼容,如果你運(yùn)行中出現(xiàn)了問題,嘗試更換對(duì)應(yīng)的版本。
Windows 10 SDK 根據(jù)你的windows版本選擇,如果說windows10就選擇win10


將cl.exe的目錄添加到path中。該程序在筆者的C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.36.32532\bin\Hostx64\x86下,請(qǐng)根據(jù)自己安裝目錄去尋找。

3、安裝native-image
使用x64 Native Tools Command Prompt for VS 2022 窗口來安裝aot編譯器native-image。

gu install native-image:該處我已經(jīng)提前安裝。

4、下載spring boot3 native demo
下載demo源碼倉(cāng)庫(kù)地址spring-native-demo
其中demo中添加了spring-native插件。
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
</plugin>
springboot3.0配置文件中已經(jīng)添加了插件依賴,插件的作用就是編譯java并且使用操作系統(tǒng)的可執(zhí)行內(nèi)核程序進(jìn)行編譯。

5、編譯可執(zhí)行文件
據(jù)說在linux和mac中是可以直接使用該插件進(jìn)行編譯,但在windows中,需要使用 x64 Native Tools Command Prompt for VS 2022 窗口進(jìn)行編譯。
我們這里采用比較方便的方式進(jìn)行 x64 Native Tools Command Prompt for VS 2022 窗口編譯,該窗口實(shí)際上是使用cmd窗口執(zhí)行以下目標(biāo)指令,所以我們只需要在idea中設(shè)置shell path為cmd+執(zhí)行指令就可以直接使用idea的Terminal窗口進(jìn)行編譯了。



配置好后,Terminal中打印native窗口內(nèi)容,就代表配置成功了。

此時(shí)只需要我們執(zhí)行編譯指令mvn install -Pnative native:compile -DskipTests=true,等待后即可編譯成功。會(huì)在target目錄下生成exe可執(zhí)行文件。

6、執(zhí)行可執(zhí)行文件效果
執(zhí)行exe文件。

在配置了spring data jpamysql數(shù)據(jù)源的情況下,啟動(dòng)時(shí)間很樂觀。

二、Linux
1、graalvm安裝
下載graalvm linux與native-image的安裝jar。


graalvm jdk解壓后到任意目錄后,將該目錄添加到環(huán)境變量
vim /etc/profile
source /etc/profile


2、安裝gcc
yum install -y gcc
3、安裝native-image
使用剛下載的安裝包安裝native-image
gu -L install native-image-installable-svm-java17-linux-amd64-22.3.0.jar

4、克隆springboot3 native demo,編譯可執(zhí)行文件
git clone https://github.com/wdragondragon/spring-native-demo.git
cd spring-native-demo/
mvn install -Pnative native:compile -X -DskipTests=true</pre>
過程中可能會(huì)出現(xiàn)status 137的異常,該異常的出現(xiàn)是編譯時(shí)內(nèi)存不足導(dǎo)致oom,請(qǐng)?jiān)诰庉?code>mvn啟動(dòng)腳本,提高堆內(nèi)存大小。

發(fā)現(xiàn)會(huì)使用環(huán)境變量MAVEN_OPTS來追加mvn啟動(dòng)的jvm參數(shù)。

隨后在/etc/profile添加以下內(nèi)容,source /etc/profile后,再次執(zhí)行編譯。即可編譯成功。

5、執(zhí)行可執(zhí)行文件效果
編譯成功后,target/spring-native-demo為可執(zhí)行文件,啟動(dòng)可執(zhí)行文件。配置了jpa的啟動(dòng)速度也十分樂觀。

三、可能會(huì)出現(xiàn)的異常
在筆者編寫該文章時(shí),最新的springboot的ga版本已經(jīng)是3.1.1了。有可能會(huì)有讀者會(huì)將springboot的版本提升到最新。

但在基于最新GA版本的springboot編譯成可執(zhí)行文件后,啟動(dòng)時(shí)會(huì)出現(xiàn)以下問題。會(huì)導(dǎo)致JpaRepository的interface method派生查詢出現(xiàn)動(dòng)態(tài)代理的異常。

可以查看demo中的commit history,其中我嘗試過使用-H:DynamicProxyConfigurationFiles指定dynamic-proxy.json來解決,也嘗試過引入舊版springboot2.x中的spring-native來申明Hint。但都無濟(jì)于事。最后在graalvm-reachability-metadata這個(gè)子項(xiàng)目中的issue中找到一些蛛絲馬跡。
其中感謝derkoe的提醒,我將springboot的版本降低到了上一個(gè)GA版本3.0.8,然后再編譯十分順利了。
