GraalVM Native 尝试

GraalVM 是一个支持原生图像编译的 JDK,可以直接把 java 代码编译为可执行文件,不需要 jvm 就可以运行。而 Spring 刚好也支持了 GraalVM,现在来尝试一下。

在 MacOS 上安装 GraalVM

可查看官网的安装指南:

Installation on macOS Platforms

使用 Homebrew 安装 GraalVM

官网提供了二进制文件,为了方便可以直接使用 Homebrew 进行安装:

brew install graalvm-jdk

配置环境变量

  • 将 GraalVM 的 bin 路径加入到 PATH 环境变量
  • 配置 JAVA_HOME 环境变量指向 GraalVM 的安装目录

查看 jdk 安装路径

# 查看本机安装的所有 jdk
/usr/libexec/java_home -V

Image

可以看到 GraalVM 的安装路径为 /Library/Java/JavaVirtualMachines/graalvm-21.jdk/Contents/Home

配置环境变量:

echo "export JAVA_HOME='/Library/Java/JavaVirtualMachines/graalvm-21.jdk/Contents/Home'" >> ~/.zshrc
echo "export PATH='$JAVA_HOME/bin:$PATH'" >> ~/.zshrc
 
source ~/.zshrc

删除隔离属性(MacOS Catalina及更高版本)

此时运行 java --version 会报错,因为 MacOS 的保护机制,需要删除隔离属性:

sudo xattr -r -d com.apple.quarantine /Library/Java/JavaVirtualMachines/graalvm-21.jdk

此时再运行 java --version 就可以看到具体版本了:

Image


创建一个 Spring Boot 项目尝试 GraalVM

使用 https://start.spring.io 网站提供的 Spring 项目脚手架,或者直接使用 IDEA 提供的项目创建功能

Image

核心依赖和插件大概是这些:

plugins {
    id("org.springframework.boot") version "3.2.3"
    id("io.spring.dependency-management") version "1.1.4"
    id("org.graalvm.buildtools.native") version "0.9.28"
    kotlin("jvm") version "1.9.22"
    kotlin("plugin.spring") version "1.9.22"
}
 
dependencies {
    implementation("org.springframework.boot:spring-boot-starter-webflux")
    implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
    implementation("io.projectreactor.kotlin:reactor-kotlin-extensions")
    implementation("org.jetbrains.kotlin:kotlin-reflect")
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor")
    testImplementation("org.springframework.boot:spring-boot-starter-test")
    testImplementation("io.projectreactor:reactor-test")
}

添加一点示例代码:

@RestController
class HelloController {
    @GetMapping("/hello")
    suspend fun hello() = "Hello GraalVM"
}

编译项目:

./gradlew nativeCompile

编译完成的结果如下,M1 Pro 芯片大概花了 2分26 秒编译完成,感觉速度还可以🥳,编译结果是在<project path>/build/native/nativeCompile/<project name> 下。

编译出来的可执行文件大小为 96.5 MB,感觉还是挺大的,不过毕竟引入了整个 Spring 的依赖和 kotlin 依赖。纯 java 可能会更小一些。

Image

接下来就是重头戏,直接运行可执行文件:

Image

启动速度相当快,一瞬间就起来了,访问下接口:

Image

内存占用 53.6 MB,感觉还行 😋

Image