Developing Your First GraalVM Native Application

现在我们已经对 GraalVM Native Images 和 Spring 即时引擎的工作原理有了很好的了解,我们可以了解如何创建一个应用程序。 有两种主要的构建 Spring Boot 原生图像应用程序的方式:

  • 使用 Spring Boot 对 Cloud Native Buildpacks 的支持生成包含原生可执行文件的轻量级容器。

  • 使用 GraalVM Native Build Tools 生成原生可执行文件。

启动新的原生 Spring Boot 项目的最简单方法是访问 start.spring.io ,添加 “GraalVM Native Support” 依赖并生成该项目。包含的 HELP.md 文件将提供入门提示。

Sample Application

我们需要一个示例应用程序,我们可以用它来创建我们的原生映像。对于我们的目的,在 “Developing Your First Spring Boot Application” 部分中介绍的简单的 “Hello World!” Web 应用程序就足够了。

总而言之,我们的主应用程序代码如下所示:

此应用程序使用 Spring MVC 和嵌入式 Tomcat,两者都经过测试和验证,可与 GraalVM 原生映像配合使用。

Building a Native Image Using Buildpacks

Spring Boot 为 Maven 和 Gradle 直接添加了对原生映像的 buildpack 支持。这意味着你只需键入一个命令,就可以快速地将一个明智的映像导入到本地运行的 Docker 守护进程中。生成的映像不包含 JVM,而是静态地编译原生的映像。这会导致较小的映像。

用于映像的构建器是 paketobuildpacks/builder-jammy-tiny:latest 。它体积小巧,攻击面减少,但你也可以使用 paketobuildpacks/builder-jammy-base:latestpaketobuildpacks/builder-jammy-full:latest 以便在需要时在映像中使用更多工具。

System Requirements

应当安装 Docker。有关更多详细信息,请参阅 Get Docker 。如果你使用 Linux,请参阅 Configure it to allow non-root user

你可以运行 docker run hello-world (不带有 sudo )以检查 Docker 守护进程是否能够按预期访问。有关更多详细信息,请查阅 MavenGradle Spring Boot 插件文档。

在 macOS 上,建议将分配给 Docker 的内存增加到至少 8GB ,并可能也增加更多 CPU。有关更多详细信息,请参阅此 Stack Overflow answer 。在 Microsoft Windows 上,请确保启用 Docker WSL 2 backend 以提高性能。

Using Maven

若要使用 Maven 构建一个原生图像容器,应确保你的 pom.xml 文件使用 spring-boot-starter-parentorg.graalvm.buildtools:native-maven-plugin 。你应该有一个如下所示的 <parent> 部分:

<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>{version-spring-boot}</version>
</parent>

此外,你还应该在 <build> <plugins> 部分中添加以下内容:

<plugin>
	<groupId>org.graalvm.buildtools</groupId>
	<artifactId>native-maven-plugin</artifactId>
</plugin>

spring-boot-starter-parent 声明了一个 native 配置文件,其中配置了创建原生映像所需的执行。你可以使用命令行上的 -P 标志激活配置文件。

如果你不想使用 spring-boot-starter-parent ,则需要从 Spring Boot 的插件配置 process-aot 目标的执行,以及从 Native Build Tools 插件配置 add-reachability-metadata 目标的执行。

要生成此映像,你可以运行 spring-boot:build-image 目标,激活 native 配置:

$ mvn -Pnative spring-boot:build-image

Using Gradle

Spring Boot Gradle 插件在应用 GraalVM Native Image 插件时会自动配置 AOT 任务。你应该检查你的 Gradle 构建是否包含了一个包含 org.graalvm.buildtools.nativeplugins 块。

只要应用 org.graalvm.buildtools.native 插件,bootBuildImage 任务就会生成原生映像而不是 JVM。你可以使用以下内容运行该任务:

$ gradle bootBuildImage

Running the example

运行了适当的构建命令后,应提供一个 Docker 映像。你可以使用 docker run 启动你的应用程序:

$ docker run --rm -p 8080:8080 docker.io/library/myproject:0.0.1-SNAPSHOT

你应该会看到类似于以下内容的输出:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::  (v{version-spring-boot})
....... . . .
....... . . . (log output here)
....... . . .
........ Started MyApplication in 0.08 seconds (process running for 0.095)

启动时间因机器而异,但它应该比在 JVM 上运行的 Spring Boot 应用程序快得多。

如果你用网络浏览器打开 http://localhost:8080,你应该会看到以下输出:

Hello World!

要正常退出应用程序,请按 ctrl-c

Building a Native Image using Native Build Tools

如果你想直接生成一个原生可执行文件而不使用 Docker,那么你可以使用 GraalVM Native 构建工具。Native 构建工具是 GraalVM 为 Maven 和 Gradle 提供的插件。你可以使用它们来执行各种 GraalVM 任务,包括生成原生映像。

Prerequisites

要使用 Native 构建工具构建原生映像,你需要在你的机器上安装 GraalVM 发行版。你可以从 {url-download-liberica-nik}[Liberica Native Image Kit 页面] 手动下载它,也可以使用像 SDKMAN! 这样的下载管理器来下载。

Linux and macOS

我们建议使用 SDKMAN! 在 macOS 或 Linux 上安装原生图像编译器。从 [role="bare"][role="bare"]https://sdkman.io 获得 SDKMAN!,并使用以下命令安装 Liberica GraalVM 发行版:

$ sdk install java {version-graal}.r17-nik
$ sdk use java {version-graal}.r17-nik

通过检查 java -version 的输出验证是否已配置了正确的版本:

$ java -version
openjdk version "17.0.5" 2022-10-18 LTS
OpenJDK Runtime Environment GraalVM 22.3.0 (build 17.0.5+8-LTS)
OpenJDK 64-Bit Server VM GraalVM 22.3.0 (build 17.0.5+8-LTS, mixed mode)

Windows

在 Windows 上,请按照 these instructions 安装 GraalVM 或 {url-download-liberica-nik}[Liberica Native Image Kit] 的 {version-graal} 版本、Visual Studio 构建工具和 Windows SDK。由于 Windows related command-line maximum length,请确保使用 x64 原生工具命令提示符来运行 Maven 或 Gradle 插件,而不是常规 Windows 命令行。

Using Maven

buildpack support 一样,你需要确保正在使用 spring-boot-starter-parent,以继承 native 配置,并且使用 org.graalvm.buildtools:native-maven-plugin 插件。

native 配置处于激活状态时,你可以调用 native:compile 目标以触发 native-image 编译:

$ mvn -Pnative native:compile

可以在 target 目录中找到原生映像可执行文件。

Using Gradle

将 Native 构建工具 Gradle 插件应用到你的项目后,Spring Boot Gradle 插件将自动触发 Spring AOT 引擎。任务依赖项会自动配置,所以你只需运行标准 nativeCompile 任务即可生成一个原生映像:

$ gradle nativeCompile

可以在 build/native/nativeCompile 目录中找到原生映像可执行文件。

Running the Example

此时,你的应用程序应该正常工作。你现在可以通过直接运行它来启动应用程序:

  • Maven

  • Gradle

$ target/myproject
$ build/native/nativeCompile/myproject

你应该会看到类似于以下内容的输出:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::  (v{version-spring-boot})
....... . . .
....... . . . (log output here)
....... . . .
........ Started MyApplication in 0.08 seconds (process running for 0.095)

启动时间因机器而异,但它应该比在 JVM 上运行的 Spring Boot 应用程序快得多。

如果你用网络浏览器打开 http://localhost:8080,你应该会看到以下输出:

Hello World!

要正常退出应用程序,请按 ctrl-c