spring boot 3 已經出來一段時間了,官方也把 GraalVM native 作為 sp3 的一個重大的功能。
那什麼是 GraalVM 呢?#
從名字就可以看出 GraalVM 是一個虛擬機,它的主要目標就是提升 java 應用程序的性能,並且消耗更少的資源。
它在 java HotSpot JVM 的基礎上添加了 JIT 編譯器和 AOT 來實現將應用編譯成為本地可執行文件。除了 java 之外,GraalVM 還支持 JavaScript、Ruby、Python 等多種編程語言。
通俗點講,GraalVM 能夠讓 Java 或其它語言用其解釋器編譯為二進制程序。用 spring boot 3 框架編寫的 Java 程序被轉換後,啟動速度更快,內存佔用更小,到達最佳性能用時更短。
為什麼需要 GraalVM?#
為什麼 Java 這麼重視 GraalVM 呢?
眾所周知,Java 作為一門老語言,漸漸跟不上新興的技術與潮流。雖然 JDK 一直在更新,但還是受限於歷史包袱的原因,船大難掉頭。
這其中雲原生,serverless,容器化這些新潮玩意就不講武德猛踹 Java 那條壞腿。雖然還沒到踹到半死不活的地步,但這是未來大勢,不可阻擋。
關於 serverless 的思考#
對於 serverless (無伺服器計算) 的 Providers (雲伺服器商) 而言,更小的內存佔用,更快的啟動速度無疑是降低成本的必然選擇。
對於 Consumer (消費者 - 企業) 而言,省去了購買伺服器及運維的錢,又支持按量計費,無疑非常有吸引力。
另一方面,AI 大模型對行業重新洗牌,但有能力訓練、部署、迭代的只有大公司,而又可以提供大模型能力的只有雲伺服器商。那 serverless 就幾乎只能成為中小公司對接 AI 的最佳選擇。
安裝 GraalVM#
在官方網站下載並解壓,完成後需配置環境變量
可以使用官方的配置方式
#注意修改下面的地址為你本地解壓的地址
setx /M PATH "C:\Program Files\Java\graalvm-ce-java11-20.3.0\bin;%PATH%"
setx /M JAVA_HOME "C:\Program Files\Java\graalvm-ce-java11-20.3.0"
也可以直接配置環境變量
win
+ i
進入設置 --- 高級系統設置 --- 環境變量,增加如下的配置
GRAALVM_HOME :解壓的路徑
JAVA_HOME :解壓的路徑
然後在path裡面配置
%GRAALVM_HOME%\bin
%JAVA_HOME%\bin
使用 cmd 的 java -version
命令查看版本,如果有 GraalVM 字樣表示成功
安裝編譯環境#
要將 Java 通過 GraalVM 編譯成二進制,需要安裝 C++ 環境
以下是通過Visual Studio安裝相關環境的方法,你也可以查看官方教程
如果你是 Windows 11,不要使用官方教程裡面的 Visual Studio 2019,而應該使用最新版
安裝下面的組件
創建 spring boot 3 項目#
使用 idea 創建
JDK 要選擇 GraalVM 的,Java 版本要選擇 17 及以上的
選擇 spring boot 3.0 以上版本,添加 GraalVM Native Support 和 Web 依賴
創建完成後 maven 文件中應有如下插件
完成後新建一個 controller 編寫一個簡單的接口
@RestController
@RequestMapping("user")
public class UserController {
@GetMapping("test")
public String test(){
return "hello world";
}
編譯及構建#
代碼寫完了,我們就要編譯了
打開 Visual Studio Build Tools x64 Native Tools Command Prompt for VS 2022
x64、x86 都是可以的,然後進入項目目錄
使用 mvn -PnativeTest test
進行編譯測試
沒有錯誤後使用 mvn native:build
進行構建,完成後會在項目目錄生成一個 exe 文件
可以看到,構建後的文件還是很大的,這是因為在構建過程中打包了一些依賴
其中大約 50M 是代碼的體積,這一部分還包含了一個 java.base
30M 是鏡像的堆體積,剩下的是其它數據
啟動 exe 文件,發現速度可以說是光速了
現有不足#
GraalVM 可以說是一個非常有意思的東西,它是 Java 對雲原生的一次勇敢嘗試,它解決了 Java 的重大弊病,但同時也帶了致命的問題。
Java 中的動態調用支持引入各種依賴,並在調用時進行指向,而 GraalVM Native 使用的 AOP (提前編譯) 是基於靜態代碼可達分析。通俗點講就是 Java 編譯時不知道你有什麼用,但在調用時就可以找到了,而 GraalVM 在編譯時則一定要指定你是誰,你有什麼用。
GraalVM 犧牲了編譯耗時,優化了啟動耗時。這當然是正確的,但它也無法動態調用了。
儘管其提供了使用反射解決的方法,但目前仍非常複雜
我嘗試引入 mybatis 的依賴,但並未使用,測試編譯就並未通過。
在 spring boot3 中使用 native image
Using GraalVM and Native Image on Windows 10