news 2026/9/9 23:16:42

Spring Boot 如何构建并运行 GraalVM Native Image 应用?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Spring Boot 如何构建并运行 GraalVM Native Image 应用?

Spring Boot 如何构建并运行 GraalVM Native Image 应用?

【免费下载链接】spring-bootSpring Boot helps you to create Spring-powered, production-grade applications and services with absolute minimum fuss.项目地址: https://gitcode.com/gh_mirrors/sp/spring-boot

如果你有一个 Spring Boot Web 应用,希望把它部署成 GraalVM Native Image 形式——一个不需要携带 JVM 的独立可执行文件,或一个不含 JVM 的轻量容器镜像——这篇文章给出 Spring Boot 官方文档中的两条完整构建路径:一条通过 Cloud Native Buildpacks 生成 Docker 镜像(本地不需要安装 GraalVM),另一条通过 GraalVM Native Build Tools 在本机生成原生可执行文件。两条路径都从同一个“Hello World”示例应用出发,覆盖构建命令、运行方式和结果验证。

准备:示例应用与构建器要求

文档使用的示例应用是一个最简单的 Spring MVC Web 应用,它同时使用了 Spring MVC 和嵌入式 Tomcat,这两者都已测试并确认可以在 GraalVM native image 中工作。主应用类如下(来自 示例源码):

package org.springframework.boot.docs.howto.nativeimage.developingyourfirstapplication.sampleapplication; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @SpringBootApplication public class MyApplication { @RequestMapping("/") String home() { return "Hello World!"; } public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); } }

文档同时建议:新建 native 项目最简单的办法是到 start.spring.io,添加GraalVM Native Support依赖后生成项目,项目自带的HELP.md会给出入门提示。

路径一:用 Cloud Native Buildpacks 构建 native 容器镜像

这是文档给出的主路径。Spring Boot 通过 Maven 和 Gradle 的 Cloud Native Buildpacks(CNB)集成,配合 Paketo Java Native Image buildpack,可以一条命令把应用构建成包含 native 可执行文件的镜像。镜像中不包含 JVM,native image 是静态编译的,因此体积更小。

两个硬性前提:

  • 构建应用的 Java 版本至少为 JDK 25,因为 Buildpacks 使用的 GraalVM native-image 版本与编译所用的 Java 版本一致;
  • 本机安装并运行着 Docker 守护进程。

系统与 Docker 检查

在 Linux 上建议配置 Docker 允许非 root 用户访问。可以用下面的命令确认 Docker daemon 可正常访问(不带sudo):

docker run hello-world

文档给出的平台建议:macOS 上建议将 Docker 分配的内存增加到至少8GB,必要时增加 CPU 核数;Windows 上建议启用 Docker 的 WSL 2 后端以获得更好性能。

Maven 构建

pom.xml需要满足两点:使用spring-boot-starter-parent,并声明org.graalvm.buildtools:native-maven-plugin<parent>部分如下(文档中该位置为{version-spring-boot}模板变量,即你使用的 Spring Boot 版本;本仓库 gradle.properties 中当前版本为4.2.0-SNAPSHOT):

<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>4.2.0-SNAPSHOT</version> </parent>

<build><plugins>部分加入:

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

spring-boot-starter-parent声明了一个nativeprofile,其中配置了生成 native image 所需的执行项(executions),用命令行-P标志激活。文档同时提示:如果不使用spring-boot-starter-parent,需要自行配置 Spring Boot 插件的process-aotgoal 和 Native Build Tools 插件的add-reachability-metadatagoal 的执行。

构建镜像只需运行:

mvn -Pnative spring-boot:build-image

Gradle 构建(替代)

Gradle 侧的机制是:Spring Boot Gradle 插件在应用了org.graalvm.buildtools.native插件后会自动配置 AOT 任务。确认你的构建脚本plugins块包含该插件后,bootBuildImage任务会生成 native image 而不是 JVM 镜像:

gradle bootBuildImage

运行容器并验证

构建完成后本地 Docker 中应有一个可用镜像,用docker run启动(下面镜像名docker.io/library/myproject:0.0.1-SNAPSHOT是文档示例,实际取决于你的项目坐标):

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

你应该看到与下面类似的输出(文档示例,启动时间随机器不同而变化,但应远快于运行在 JVM 上的 Spring Boot 应用):

. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v4.2.0-SNAPSHOT) ....... . . . ....... . . . (log output here) ....... . . . ........ Started MyApplication in 0.08 seconds (process running for 0.095)

再打开浏览器访问http://localhost:8080,应看到:

Hello World!

ctrl-c可以优雅退出应用。

补充说明 CNB 构建器:文档指出默认使用的 builder 是paketobuildpacks/builder-noble-java-tiny:latest,它体积小、攻击面小,但不含 shell 且系统库精简。如果你需要在运行镜像中带更多工具,可以把paketobuildpacks/ubuntu-noble-run:latest作为run镜像。

路径二:用 Native Build Tools 生成本地原生可执行文件

如果不想经过 Docker,而是直接得到本机可运行的原生可执行文件,使用 GraalVM 官方为 Maven 和 Gradle 提供的 Native Build Tools 插件。与路径一不同,这条路径要求本机安装 GraalVM 发行版(含 native-image 编译器)。

安装 JDK

Linux 和 macOS 上文档推荐使用 SDKMAN! 安装 Liberica GraalVM 发行版:

sdk install java 25.r25-nik sdk use java 25.r25-nik

java -version的输出确认版本已生效,文档示例输出如下:

openjdk version "25" 2025-09-16 LTS OpenJDK Runtime Environment Liberica-NIK-25.0.0-1 (build 25+37-LTS) OpenJDK 64-Bit Server VM Liberica-NIK-25.0.0-1 (build 25+37-LTS, mixed mode, sharing)

Windows 上需要安装对应版本({version-graal}在本仓库解析为 25)的 GraalVM 或 Liberica Native Image Kit、Visual Studio Build Tools 和 Windows SDK;并且由于 Windows 命令行长度限制,运行 Maven 或 Gradle 插件时必须使用 x64 Native Tools Command Prompt,而不是普通命令行。

构建

Maven 项目的前提与路径一相同:使用spring-boot-starter-parent以继承nativeprofile,并声明org.graalvm.buildtools:native-maven-plugin。激活nativeprofile 后调用native:compilegoal 触发native-image编译:

mvn -Pnative native:compile

生成的 native image 可执行文件位于target目录。

Gradle 项目应用 Native Build Tools Gradle 插件后,Spring Boot Gradle 插件会自动触发 Spring AOT 引擎,任务依赖也已自动配置,直接运行标准任务即可:

gradle nativeCompile

生成的 native image 可执行文件位于build/native/nativeCompile目录。

运行并验证

直接运行生成的可执行文件,Maven 项目为target/myproject,Gradle 项目为build/native/nativeCompile/myproject(文件名即你的应用名):

# Maven 构建产物 target/myproject # Gradle 构建产物 build/native/nativeCompile/myproject

验证方式与路径一相同:启动日志中应出现Started MyApplication in 0.08 seconds ...文档示例,实际时间随机器变化),浏览器访问http://localhost:8080应返回Hello World!,按ctrl-c优雅退出。

排查构建或运行问题

native image 采用构建期静态分析,文档明确了几个会直接影响部署的机制,排查时应对照检查:

AOT 处理生成的产物。Spring AOT 引擎在构建期生成 Java 源码、字节码以及 GraalVM JSON 提示文件(resource-config.jsonreflect-config.jsonserialization-config.jsonproxy-config.jsonjni-config.json),位于META-INF/native-image/{groupId}/{artifactId}/。Maven 的生成源码在target/spring-aot/main/sources,Gradle 在build/generated/aotSources;提示文件分别在target/spring-aot/main/resourcesbuild/generated/aotResources。文档提示生成源码可读性不错,调试应用时可以参考。

嵌套配置属性必须加注解。反射提示通常由 AOT 引擎自动为配置属性生成,但非内部类的嵌套配置属性必须标注@NestedConfigurationProperty,否则在 native image 中不可绑定。构造函数绑定时注解加在字段上,record 和 Kotlin data class 则加在参数上;所有情况下都要使用 public getter/setter,否则属性不可绑定。

缺少提示时用 Tracing Agent。Spring 会自动生成大部分反射、资源、代理提示,但某个库或模式没被识别时,GraalVM 的 native image tracing agent 可以快速定位缺失项。文档给出的做法是带 agent 直接启动应用并实际触发代码路径:

java -Dspring.aot.enabled=true \ -agentlib:native-image-agent=config-output-dir=/path/to/config-dir/ \ -jar target/myproject-0.0.1-SNAPSHOT.jar

其中/path/to/config-dir/需要替换为你指定的提示输出目录。触发完目标代码路径后按ctrl-c停止应用,agent 会在关闭时把提示文件写到该目录。你可以手动检查这些文件,也可以把它们复制到src/main/resources/META-INF/native-image/目录,作为下次 native image 构建的输入。另一种做法是运行应用测试来触发,但默认生成的提示会包含测试框架自身所需的条目,agent 支持 access-filter 文件把这部分排除。

已知限制。并非所有第三方库都支持 native image;Spring 本身不为第三方库携带提示,而是依赖 GraalVM 社区的 reachability metadata 项目。文档同时列出 AOT 的闭世界限制:应用的 Bean 不能随运行环境变化,@Profile与按 profile 区分的配置有限制,依赖“某 Bean 是否创建”来改变行为的属性(例如@ConditionalOnProperty.enabled属性)不受支持。类路径在构建期固定、不可变更,且没有懒加载,可执行文件中的一切都会在启动时载入内存。

可选分支:把已构建的可执行 jar 转换成 native image

如果你的 CI/CD 沿用 JVM 流水线,或者需要一份 OS 中立的部署产物(native-image不支持交叉编译),可以在 AOT 处理过的 Spring Boot 可执行 jar 基础上做转换。前提是jar 中必须包含 AOT 生成的资产(生成的类、JSON 提示文件等)。

pack转换时,无需本地 GraalVM。文档示例假设 AOT 处理后的 jarmyproject-0.0.1-SNAPSHOT.jar位于target目录:

pack build --builder paketobuildpacks/builder-noble-java-tiny \ --path target/myproject-0.0.1-SNAPSHOT.jar \ --env 'BP_NATIVE_IMAGE=true' \ my-application:0.0.1-SNAPSHOT

完成后同样用docker run --rm -p 8080:8080 ...启动验证。

用 GraalVM 自带的native-image工具转换(这些命令适用于 Linux 或 macOS,Windows 需要自行调整;第一条命令会删除target/native目录,请确认该目录内没有需要保留的内容,并在项目根目录执行):

rm -rf target/native mkdir -p target/native cd target/native jar -xvf ../myproject-0.0.1-SNAPSHOT.jar native-image -H:Name=myproject @META-INF/native-image/argfile -cp .:BOOT-INF/classes:`find BOOT-INF/lib | tr '\n' ':'` mv myproject ../

两个注意事项:@META-INF/native-image/argfile只有在确实需要 reachability metadata 覆盖时才会打进 jar,可能不存在;native-image-cp参数不接受通配符,所以上面的命令用findtr把所有 jar 逐一列出来。

进一步阅读

  • Developing Your First GraalVM Native Application:本文两条构建路径的完整 how-to 原文。
  • GraalVM Native Images 参考 与 Introducing GraalVM Native Images:native image 与 JVM 部署的关键差异、AOT 处理原理。
  • Advanced Native Images Topics:Tracing Agent、自定义提示(RuntimeHintsRegistrar、静态 JSON 提示文件)与已知限制的详细说明。

【免费下载链接】spring-bootSpring Boot helps you to create Spring-powered, production-grade applications and services with absolute minimum fuss.项目地址: https://gitcode.com/gh_mirrors/sp/spring-boot

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/9 23:14:55

沉浸式双语网页翻译快速上手:从安装到调校的3个环节

沉浸式双语网页翻译快速上手&#xff1a;从安装到调校的3个环节 【免费下载链接】immersive-translate 沉浸式双语网页翻译扩展 , 支持输入框翻译&#xff0c; 鼠标悬停翻译&#xff0c; PDF, Epub, 字幕文件, TXT 文件翻译 - Immersive Dual Web Page Translation Extension …

作者头像 李华
网站建设 2026/9/9 23:12:32

OpenClaw 7分钟部署教程:云服务器/Mac/Linux/Win11全平台实测

2026年3月实测&#xff1a;OpenClaw 7分钟部署教程&#xff0c;云上/Mac/Linux/Win11全流程 先说结论&#xff1a;OpenClaw 这东西&#xff0c;如果你只是听说、还没动手&#xff0c;2026年现在正是入坑的好时机。我3月初在腾讯云轻量服务器、Mac mini、Ubuntu 工作站和一台 Wi…

作者头像 李华
网站建设 2026/9/9 23:11:23

动态社区发布视频加载慢?从索引到异步化全面优化指南

在实际的社区类产品里&#xff0c;“动态太多导致发布视频加载慢”是一个很典型的性能问题。很多团队收到用户反馈后&#xff0c;第一反应是清理历史动态&#xff0c;甚至有人会开玩笑说“朋友&#xff0c;请删掉一些动态吧”。但真正的问题是&#xff1a;为什么动态数据量变大…

作者头像 李华
网站建设 2026/9/9 23:10:19

Windows 11 广告清理指南:彻底关闭推荐与推送的完整方案

最近不少朋友找我吐槽&#xff1a;新买的 Windows 11 电脑&#xff0c;用不到一周就开始“闹情绪”——开始菜单推荐区冒出一堆没用过的软件&#xff0c;锁屏界面时不时教你“小技巧”&#xff0c;设置主页催你“完成设备设置”&#xff0c;连文件资源管理器都开始推销 Microso…

作者头像 李华
网站建设 2026/9/9 23:09:31

HCL AppScan Standard 10.10.0:强化SPA与API安全测试能力

HCL AppScan Standard这名字&#xff0c;搞Web安全测试的朋友应该不陌生。圈子里叫它AppScan&#xff0c;是DAST&#xff08;动态应用安全测试&#xff09;领域的老牌工具&#xff0c;从IBM时代一路走到HCL手里&#xff0c;依然保持着比较高频的版本迭代节奏。最近这波10.10.0发…

作者头像 李华