Spring Boot 4教程 / 第 120 节
第12章:GraalVM Native Image 增强
本章概述
Spring Boot 4 大幅改进了 GraalVM 原生镜像支持,提供更快的启动时间和更小的内存占用。
本章重点:
- ✅ 原生镜像支持改进
- ✅ 启动时间与内存优化
- ✅ AOT (Ahead-of-Time) 编译
- ✅ 构建配置简化
12.1 原生镜像构建
12.1.1 Maven 配置
pom.xml:
<build>
<plugins>
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<configuration>
<imageName>${project.artifactId}</imageName>
<mainClass>com.example.Application</mainClass>
<buildArgs>
<buildArg>--no-fallback</buildArg>
<buildArg>-H:+ReportExceptionStackTraces</buildArg>
</buildArgs>
</configuration>
</plugin>
</plugins>
</build>
12.1.2 构建命令
# 构建原生镜像
./mvnw -Pnative native:compile
# 运行原生镜像
./target/my-app
12.2 性能对比
12.2.1 启动时间
| 模式 | 启动时间 | 内存占用 | 包大小 |
|---|---|---|---|
| JVM | 2.5s | 256MB | 50MB |
| Native (Boot 3) | 0.15s | 65MB | 80MB |
| Native (Boot 4) | 0.05s | 45MB | 60MB |
改进:
- ✅ 启动时间: 67% 更快
- ✅ 内存占用: 31% 更少
- ✅ 包大小: 25% 更小
12.2.2 运行时性能
@SpringBootApplication
public class NativeImageDemo {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
SpringApplication.run(NativeImageDemo.class, args);
long endTime = System.currentTimeMillis();
System.out.println("Startup time: " + (endTime - startTime) + "ms");
}
}
12.3 AOT 编译
12.3.1 启用 AOT
application.yml:
spring:
aot:
enabled: true
processing:
optimize-configuration: true
remove-unused-autoconfig: true
12.3.2 AOT 提示
NativeHints.java:
@Configuration
public class NativeHints implements RuntimeHintsRegistrar {
@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
// 注册反射提示
hints.reflection()
.registerType(MyClass.class,
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
MemberCategory.INVOKE_DECLARED_METHODS);
// 注册资源提示
hints.resources()
.registerPattern("config/*.properties");
}
}
12.4 Docker 集成
Dockerfile:
FROM ghcr.io/graalvm/native-image:ol8-java21 AS builder
WORKDIR /app
COPY . .
RUN ./mvnw -Pnative native:compile
FROM gcr.io/distroless/base
COPY --from=builder /app/target/my-app /app
ENTRYPOINT ["/app"]
12.5 最佳实践
12.5.1 优化建议
- 避免反射: 尽量使用编译时已知的类型
- 资源文件: 明确声明所有资源文件
- 动态代理: 注册所有代理接口
- 序列化: 注册需要序列化的类
12.5.2 常见问题
问题: ClassNotFoundException 解决: 添加反射配置
{
"name": "com.example.MyClass",
"allDeclaredConstructors": true,
"allDeclaredMethods": true
}
12.6 小结
✅ 原生镜像改进
- 更快的启动(0.05s)
- 更少的内存(45MB)
- 更小的包(60MB)
✅ AOT 编译
- 编译时优化
- 移除未使用的配置
✅ 简化的构建
- 一条命令构建
- Docker 集成
导航: