Spring
團隊致力於為Spring
應用程式提供原生映像支援已經有一段時間了。在SpringBoo2.x
的Spring Native
實驗專案中醞釀了3年多之後,隨著Spring Framework 6
和Spring Boot 3
的釋出,對應的專案就是Spring Native
,原生映象支援將會發布GA
版本(換言之就是,Native Image
相關支援會在Spring Boot 3
的GA
版本中一起釋出)。
前面這一段簡介摘抄自參考資料中的《Native Support in Spring Boot 3.0.0-M5》
筆者在寫這篇文章(2022-10-28
)前後SpringBoot
尚未釋出3.x GA
,版本3.0.0-M5+
算是GA
前相對穩定的版本,這裡選用當前3.x
的最新非GA
版本3.0.0-RC1
進行調研。
Native Image
,這裡直譯為原生映象或者本地映象,是一種提前將(Java
)程式碼編譯為二進位制檔案(原生可執行檔案,native executable
)的技術。原生可執行檔案只包含執行時所需要的程式碼,即應用程式類、標準庫類、語言執行時和來自JDK
的靜態連結的原生程式碼(也就是這樣的二進位制檔案可以直接執行,不需要額外安裝JDK
)。由原生映象生成的可執行檔案有幾個重要的優點:
Java
虛擬機器器所需資源的一小部分,因此執行成本更低Spring Boot 3
中使用GraalVM
方案提供Native Image
支援。
在https://www.graalvm.org/downloads - Download GraalVM頁面中下載對應作業系統的GraalVM
:
筆者開發環境使用的作業系統是Windows10
,下載和選用下圖中的安裝包:
解壓完成後設定一下JAVA_HOME
、GRAALVM_HOME
並且把GRAALVM_HOME\bin
新增到PATH
中。完成後可以執行一下java -version
進行驗證:
如果已經安裝了其他版本的JDK,先暫時全域性替換為GraalVM,也就是JAVA_HOME、GRAALVM_HOME同時設定為GraalVM的解壓目錄,因為目前看來這樣做才能正常打包原生映象
確定GraalVM
版本無誤,到此安裝完成。另外,需要設定好了Maven
,建議重新安裝一個3.6.x+
版本的Maven
並且把MAVEN_HOME\bin
新增到PATH
中。
新建一個命名為spring-boot-native-image
的Maven
專案或者模組,選用剛才下載好的GraalVM
:
專案的POM
檔案引入下面幾組依賴:
spring
的快照repository
,因為需要下載RC1
版本依賴,暫時不能從中央倉庫拉取spring-boot-starter-parent
,定義版本為RC1
native-maven-plugin
外掛,用於原生映象打包spring-boot-starter-web
,用於構建一個簡單的web
專案<!-- spring-boot-starter-parent -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.0-RC1</version>
</parent>
<!-- repository -->
<repositories>
<repository>
<id>spring-snapshots</id>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<url>https://repo.spring.io/snapshot</url>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<url>https://repo.spring.io/milestone</url>
</pluginRepository>
</pluginRepositories>
<!-- spring-boot-starter-web -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<!-- native-maven-plugin -->
<plugins>
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<version>0.9.16</version>
<extensions>true</extensions>
<executions>
<execution>
<id>build-native</id>
<goals>
<goal>compile-no-fork</goal>
</goals>
<phase>package</phase>
</execution>
<execution>
<id>test-native</id>
<goals>
<goal>test</goal>
</goals>
<phase>test</phase>
</execution>
</executions>
<configuration>
<mainClass>cn.vlts.NativeApplication</mainClass>
<imageName>native-app</imageName>
<buildArgs>
<buildArg>--verbose</buildArg>
</buildArgs>
</configuration>
</plugin>
</plugins>
最終的POM
檔案看起來如下:
專案中只有一個啟動類cn.vlts.NativeApplication
,編寫了main
方法和一個用於整合測試的控制器方法:
@RestController
@SpringBootApplication
public class NativeApplication {
public static void main(String[] args) {
SpringApplication.run(NativeApplication.class, args);
}
@GetMapping(path = "/hello")
public ResponseEntity<String> hello() {
return ResponseEntity.ok("world");
}
}
完成專案設定和程式碼編寫後,執行下面的Maven
命令進行打包:
mvn package -Pnative
打包過程可能會遇到下面的問題:
Default native-compiler executable 'cl.exe' not found via environment variable PATH
解決方案在Stackoverflow
對應的問題回答中找到:
其實就是在Window
作業系統開發環境下基於GraalVM
構建原生映象依賴Microsoft Visual C++ (MSVC)
,建議安裝MSVC 2017 15.5.5+
,可以安裝Visual Studio (2019)
並且安裝對應的MSVC
。
因為很早之前筆者在偵錯Rust
時候已經安裝過Visual Studio 2019
用於其debug
工具鏈,這裡無須進行安裝。在安裝Visual Studio
勾選MSVC vXXX
的元件進行安裝即可,然後需要把對應的MSVC
工具的bin
目錄新增到PATH
中(這個目錄一般是VS_HOME\VC\Tools\MSVC\版本號\bin\Hostx64\x64
):
stdio.h
庫檔案報錯或者找不到主類Main entry point class 'app.jar' not found x.y.Application
其實還是因為MSVC
的問題,在GraalVM
檔案中有提示如下:
簡單來說就是必須在Visual Studio
自帶的命令列工具x64 Native Tools Command Prompt
中執行native image
相關命令,這個命令列工具初始化如下:
在x64 Native Tools Command Prompt
中先進入目標專案根目錄,然後執行mvn -Pnative package
:
最終看到BUILD SUCCESS
字眼,專案的target
目錄下可以看到一個.exe
和一個.jar
檔案,而.exe
檔案就是前面一直提到的可執行的二進位制檔案:
直接執行它:
可以看到這個檔案執行完全不依賴外部Java
虛擬機器器,並且啟動速度極快(600
毫秒左右),可以用POSTMAN
等工具測試程式介面:
到此可以驗證程式功能正常。
SpringBoot3.x
原生映象正式釋出後會是SpringBoot
在雲原生領域的一個巨大進步,讓我們拭目以待。但是就目前來看,常用的Windows
開發環境下想要嘗試native image
技術需要解決比較多的問題,Linux
和Unix
平臺下尚未驗證,希望後面的版本迭代能夠降低使用難度並且支援一個命令多平臺打包的功能。
參考資料:
(本文完 c-2-d e-a-20221030)