1. GraalVM 原生镜像基础
1.1 核心概念
# 原生镜像构建概念模型
from enum import Enum
from dataclasses import dataclass
from typing import List, Dict, Optional
class CompilationPhase(Enum):
"""编译阶段"""
ANALYSIS = "analysis" # 静态分析阶段
UNIVERSE_BUILDING = "universe" # 构建闭世界
PARSING = "parsing" # 解析阶段
INLINING = "inlining" # 内联优化
COMPILING = "compiling" # 编译阶段
CREATING_IMAGE = "creating" # 创建镜像
class OptimizationLevel(Enum):
"""优化级别"""
O0 = "O0" # 无优化
O1 = "O1" # 基础优化
O2 = "O2" # 标准优化
O3 = "O3" # 高级优化
class ImageKind(Enum):
"""镜像类型"""
EXECUTABLE = "executable" # 可执行文件
SHARED_LIBRARY = "shared" # 共享库
STATIC_LIBRARY = "static" # 静态库
@dataclass
class BuildConfiguration:
"""构建配置"""
main_class: str
classpath: List[str]
optimization_level: OptimizationLevel
image_kind: ImageKind
enable_preview: bool = False
enable_assertions: bool = False
enable_monitoring: bool = False
max_heap_size: Optional[str] = None
@dataclass
class ReflectionEntry:
"""反射配置条目"""
name: str
all_declared_constructors: bool = False
all_declared_methods: bool = False
all_declared_fields: bool = False
all_public_constructors: bool = False
all_public_methods: bool = False
all_public_fields: bool = False
@dataclass
class ResourceEntry:
"""资源配置条目"""
pattern: str
condition: Optional[str] = None
@dataclass
class BuildResult:
"""构建结果"""
success: bool
image_path: str
image_size: int
build_time: float
peak_memory: int
warnings: List[str]
errors: List[str]
class NativeImageBuilder:
"""原生镜像构建器"""
def __init__(self, config: BuildConfiguration):
self.config = config
self.reflection_config: List[ReflectionEntry] = []
self.resource_config: List[ResourceEntry] = []
def add_reflection_config(self, entry: ReflectionEntry):
"""添加反射配置"""
self.reflection_config.append(entry)
def add_resource_config(self, entry: ResourceEntry):
"""添加资源配置"""
self.resource_config.append(entry)
def build(self) -> BuildResult:
"""执行构建"""
print(f"开始构建原生镜像: {self.config.main_class}")
# 模拟构建过程
phases = [
CompilationPhase.ANALYSIS,
CompilationPhase.UNIVERSE_BUILDING,
CompilationPhase.PARSING,
CompilationPhase.INLINING,
CompilationPhase.COMPILING,
CompilationPhase.CREATING_IMAGE
]
for phase in phases:
print(f"执行阶段: {phase.value}")
return BuildResult(
success=True,
image_path="./target/spring-native-demo",
image_size=45 * 1024 * 1024, # 45MB
build_time=120.5, # 2分钟
peak_memory=4 * 1024 * 1024 * 1024, # 4GB
warnings=[],
errors=[]
)
# 使用示例
config = BuildConfiguration(
main_class="com.example.demo.Application",
classpath=["/app/target/classes", "/app/target/lib/*"],
optimization_level=OptimizationLevel.O2,
image_kind=ImageKind.EXECUTABLE,
max_heap_size="512m"
)
builder = NativeImageBuilder(config)
# 添加反射配置
builder.add_reflection_config(ReflectionEntry(
name="com.example.demo.model.User",
all_declared_constructors=True,
all_declared_methods=True,
all_declared_fields=True
))
# 添加资源配置
builder.add_resource_config(ResourceEntry(
pattern="application*.yml"
))
result = builder.build()
print(f"构建结果: {result}")
1.2 构建流程
// 原生镜像构建流程示例
public class NativeImageBuildProcess {
public static void main(String[] args) {
// 1. 静态分析阶段
performStaticAnalysis();
// 2. 闭世界构建
buildClosedWorld();
// 3. 代码生成
generateNativeCode();
// 4. 链接优化
performLinking();
// 5. 创建可执行文件
createExecutable();
}
private static void performStaticAnalysis() {
System.out.println("[1/5] 执行静态分析...");
// 分析所有可达的类、方法、字段
// 检测反射使用
// 分析资源访问
System.out.println(" - 分析可达性图");
System.out.println(" - 检测反射调用");
System.out.println(" - 扫描资源文件");
}
private static void buildClosedWorld() {
System.out.println("[2/5] 构建闭世界假设...");
// 确定最终的类集合
// 移除未使用的代码
System.out.println(" - 确定最终类集合");
System.out.println(" - 移除死代码");
}
private static void generateNativeCode() {
System.out.println("[3/5] 生成原生代码...");
// 将字节码转换为机器码
// 应用优化
System.out.println(" - 字节码转换");
System.out.println(" - 应用优化");
}
private static void performLinking() {
System.out.println("[4/5] 执行链接...");
// 链接原生库
// 解析符号
System.out.println(" - 链接系统库");
System.out.println(" - 解析符号引用");
}
private static void createExecutable() {
System.out.println("[5/5] 创建可执行文件...");
// 生成最终的可执行文件
System.out.println(" - 生成可执行文件");
System.out.println("构建完成!");
}
}
2. Maven 构建配置
2.1 基础配置
<!-- pom.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>spring-native-demo</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<name>Spring Native Demo</name>
<description>Spring Native 原生镜像示例</description>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- Spring Boot 版本 -->
<spring-boot.version>3.2.0</spring-boot.version>
<!-- GraalVM 版本 -->
<graalvm.version>22.3.0</graalvm.version>
<!-- Native Build Tools 版本 -->
<native-build-tools.version>0.9.28</native-build-tools.version>
<!-- 原生镜像配置 -->
<native.maven.plugin.version>0.9.28</native.maven.plugin.version>
<main.class>com.example.demo.Application</main.class>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- Spring Boot Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- H2 数据库 -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<!-- 测试依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Spring Boot Maven Plugin -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<mainClass>${main.class}</mainClass>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Native Build Tools Plugin -->
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<version>${native.maven.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<mainClass>${main.class}</mainClass>
<buildArgs>
<!-- 基础配置 -->
<buildArg>--no-fallback</buildArg>
<buildArg>--install-exit-handlers</buildArg>
<buildArg>--enable-url-protocols=http,https</buildArg>
<!-- 内存配置 -->
<buildArg>-J-Xmx8g</buildArg>
<buildArg>-J-Xms4g</buildArg>
<!-- 优化配置 -->
<buildArg>-O2</buildArg>
<buildArg>--gc=G1</buildArg>
<!-- 调试信息 -->
<buildArg>--verbose</buildArg>
<buildArg>--enable-monitoring=heapdump,jfr</buildArg>
<!-- 静态链接 -->
<buildArg>--static</buildArg>
<buildArg>--libc=musl</buildArg>
</buildArgs>
<systemProperties>
<spring.native.remove-unused-autoconfig>true</spring.native.remove-unused-autoconfig>
<spring.native.remove-yaml-support>false</spring.native.remove-yaml-support>
</systemProperties>
</configuration>
</plugin>
<!-- Compiler Plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>17</source>
<target>17</target>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>
<!-- 原生镜像构建 Profile -->
<profiles>
<profile>
<id>native</id>
<build>
<plugins>
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<executions>
<execution>
<id>build-native</id>
<goals>
<goal>compile-no-fork</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<!-- 测试原生镜像 Profile -->
<profile>
<id>nativeTest</id>
<build>
<plugins>
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<executions>
<execution>
<id>test-native</id>
<goals>
<goal>test</goal>
</goals>
<phase>test</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
2.2 Gradle 构建配置
// build.gradle
plugins {
id 'org.springframework.boot' version '3.2.0'
id 'io.spring.dependency-management' version '1.1.4'
id 'org.graalvm.buildtools.native' version '0.9.28'
id 'java'
}
group = 'com.example'
version = '1.0.0'
java.sourceCompatibility = JavaVersion.VERSION_17
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
runtimeOnly 'com.h2database:h2'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
// 原生镜像配置
graalvmNative {
binaries {
main {
mainClass = 'com.example.demo.Application'
buildArgs.addAll([
'--no-fallback',
'--install-exit-handlers',
'--enable-url-protocols=http,https',
'-J-Xmx8g',
'-J-Xms4g',
'-O2',
'--gc=G1',
'--verbose',
'--enable-monitoring=heapdump,jfr'
])
systemProperties = [
'spring.native.remove-unused-autoconfig': 'true',
'spring.native.remove-yaml-support': 'false'
]
}
test {
buildArgs.addAll([
'--no-fallback',
'-J-Xmx4g'
])
}
}
// 工具链配置
toolchainDetection = false
}
// 编译配置
tasks.withType(JavaCompile) {
options.compilerArgs += '-parameters'
}
// 测试配置
tasks.named('test') {
useJUnitPlatform()
}
// 自定义任务
task buildNativeImage(type: Exec) {
dependsOn 'nativeCompile'
description = '构建原生镜像'
group = 'build'
doFirst {
println '开始构建原生镜像...'
}
doLast {
println '原生镜像构建完成!'
def imageFile = file("build/native/nativeCompile/spring-native-demo")
if (imageFile.exists()) {
def sizeInMB = imageFile.length() / (1024 * 1024)
println "镜像大小: ${sizeInMB.round(2)} MB"
}
}
}
3. 配置文件优化
3.1 反射配置
// src/main/resources/META-INF/native-image/reflect-config.json
[
{
"name": "com.example.demo.model.User",
"allDeclaredConstructors": true,
"allDeclaredMethods": true,
"allDeclaredFields": true,
"allPublicConstructors": true,
"allPublicMethods": true,
"allPublicFields": true
},
{
"name": "com.example.demo.dto.UserDto",
"allDeclaredConstructors": true,
"allDeclaredMethods": true,
"allDeclaredFields": true
},
{
"name": "com.example.demo.dto.CreateUserRequest",
"allDeclaredConstructors": true,
"allDeclaredMethods": true,
"allDeclaredFields": true
},
{
"name": "java.lang.String",
"methods": [
{"name": "<init>", "parameterTypes": []},
{"name": "<init>", "parameterTypes": ["char[]"]},
{"name": "valueOf", "parameterTypes": ["java.lang.Object"]}
]
},
{
"name": "java.lang.Long",
"methods": [
{"name": "<init>", "parameterTypes": ["long"]},
{"name": "valueOf", "parameterTypes": ["long"]}
]
},
{
"name": "java.lang.Integer",
"methods": [
{"name": "<init>", "parameterTypes": ["int"]},
{"name": "valueOf", "parameterTypes": ["int"]}
]
},
{
"name": "java.time.LocalDateTime",
"allDeclaredConstructors": true,
"allDeclaredMethods": true
},
{
"name": "org.springframework.boot.context.properties.ConfigurationProperties",
"allDeclaredMethods": true
},
{
"name": "org.springframework.web.bind.annotation.RequestMapping",
"allDeclaredMethods": true
},
{
"name": "org.springframework.web.bind.annotation.RestController",
"allDeclaredMethods": true
},
{
"name": "org.springframework.stereotype.Service",
"allDeclaredMethods": true
},
{
"name": "org.springframework.stereotype.Repository",
"allDeclaredMethods": true
},
{
"name": "javax.persistence.Entity",
"allDeclaredMethods": true
},
{
"name": "javax.persistence.Id",
"allDeclaredMethods": true
},
{
"name": "javax.persistence.GeneratedValue",
"allDeclaredMethods": true
},
{
"name": "javax.persistence.Column",
"allDeclaredMethods": true
}
]
3.2 资源配置
// src/main/resources/META-INF/native-image/resource-config.json
{
"resources": {
"includes": [
{
"pattern": "\\Qapplication.yml\\E"
},
{
"pattern": "\\Qapplication.yaml\\E"
},
{
"pattern": "\\Qapplication.properties\\E"
},
{
"pattern": "\\Qapplication-.*\\.yml\\E"
},
{
"pattern": "\\Qapplication-.*\\.yaml\\E"
},
{
"pattern": "\\Qapplication-.*\\.properties\\E"
},
{
"pattern": "\\QMETA-INF/spring.factories\\E"
},
{
"pattern": "\\QMETA-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports\\E"
},
{
"pattern": "\\Qorg/hibernate/validator/ValidationMessages.properties\\E"
},
{
"pattern": "\\QValidationMessages.properties\\E"
},
{
"pattern": "\\Qstatic/.*\\E"
},
{
"pattern": "\\Qtemplates/.*\\E"
},
{
"pattern": "\\Qschema.sql\\E"
},
{
"pattern": "\\Qdata.sql\\E"
},
{
"pattern": "\\Qlogback-spring.xml\\E"
},
{
"pattern": "\\Qlogback.xml\\E"
}
]
},
"bundles": [
{
"name": "messages",
"locales": ["zh_CN", "en_US"]
},
{
"name": "ValidationMessages",
"locales": ["zh_CN", "en_US"]
}
]
}
3.3 序列化配置
// src/main/resources/META-INF/native-image/serialization-config.json
[
{
"name": "com.example.demo.model.User"
},
{
"name": "com.example.demo.dto.UserDto"
},
{
"name": "com.example.demo.dto.CreateUserRequest"
},
{
"name": "java.lang.String"
},
{
"name": "java.lang.Long"
},
{
"name": "java.lang.Integer"
},
{
"name": "java.time.LocalDateTime"
},
{
"name": "java.util.ArrayList"
},
{
"name": "java.util.HashMap"
},
{
"name": "java.util.LinkedHashMap"
},
{
"name": "org.springframework.http.ResponseEntity"
},
{
"name": "org.springframework.validation.BindingResult"
}
]
3.4 代理配置
// src/main/resources/META-INF/native-image/proxy-config.json
[
{
"interfaces": [
"com.example.demo.repository.UserRepository",
"org.springframework.data.repository.Repository",
"org.springframework.data.jpa.repository.JpaRepository",
"org.springframework.transaction.annotation.Transactional"
]
},
{
"interfaces": [
"com.example.demo.service.UserService"
]
},
{
"interfaces": [
"org.springframework.aop.SpringProxy",
"org.springframework.aop.framework.Advised",
"org.springframework.core.DecoratingProxy"
]
}
]
4. 构建脚本
4.1 Linux/macOS 构建脚本
#!/bin/bash
# build-native.sh
set -e
echo "=== Spring Native 原生镜像构建脚本 ==="
# 配置变量
APP_NAME="spring-native-demo"
MAIN_CLASS="com.example.demo.Application"
BUILD_DIR="target"
NATIVE_IMAGE_DIR="$BUILD_DIR/native-image"
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 日志函数
log_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
log_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
log_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# 检查环境
check_environment() {
log_info "检查构建环境..."
# 检查 Java 版本
if ! command -v java &> /dev/null; then
log_error "Java 未安装或不在 PATH 中"
exit 1
fi
JAVA_VERSION=$(java -version 2>&1 | head -n1 | cut -d'"' -f2 | cut -d'.' -f1)
if [ "$JAVA_VERSION" -lt 17 ]; then
log_error "需要 Java 17 或更高版本,当前版本: $JAVA_VERSION"
exit 1
fi
log_success "Java 版本检查通过: $JAVA_VERSION"
# 检查 GraalVM
if ! command -v native-image &> /dev/null; then
log_error "GraalVM native-image 未安装或不在 PATH 中"
log_info "请安装 GraalVM 并运行: gu install native-image"
exit 1
fi
log_success "GraalVM native-image 检查通过"
# 检查 Maven
if ! command -v mvn &> /dev/null; then
log_error "Maven 未安装或不在 PATH 中"
exit 1
fi
log_success "Maven 检查通过"
}
# 清理构建目录
clean_build() {
log_info "清理构建目录..."
mvn clean
rm -rf "$NATIVE_IMAGE_DIR"
mkdir -p "$NATIVE_IMAGE_DIR"
log_success "构建目录清理完成"
}
# 编译 Java 代码
compile_java() {
log_info "编译 Java 代码..."
mvn compile
log_success "Java 代码编译完成"
}
# 运行测试
run_tests() {
log_info "运行单元测试..."
mvn test
log_success "单元测试通过"
}
# 打包应用
package_app() {
log_info "打包应用..."
mvn package -DskipTests
log_success "应用打包完成"
}
# 构建原生镜像
build_native_image() {
log_info "开始构建原生镜像..."
# 记录开始时间
START_TIME=$(date +%s)
# 构建原生镜像
mvn -Pnative native:compile
# 记录结束时间
END_TIME=$(date +%s)
BUILD_TIME=$((END_TIME - START_TIME))
log_success "原生镜像构建完成,耗时: ${BUILD_TIME}s"
# 检查生成的文件
NATIVE_BINARY="$BUILD_DIR/$APP_NAME"
if [ -f "$NATIVE_BINARY" ]; then
FILE_SIZE=$(du -h "$NATIVE_BINARY" | cut -f1)
log_success "原生镜像文件: $NATIVE_BINARY (大小: $FILE_SIZE)"
# 设置执行权限
chmod +x "$NATIVE_BINARY"
log_success "已设置执行权限"
else
log_error "原生镜像文件未找到: $NATIVE_BINARY"
exit 1
fi
}
# 验证原生镜像
verify_native_image() {
log_info "验证原生镜像..."
NATIVE_BINARY="$BUILD_DIR/$APP_NAME"
# 检查文件类型
FILE_TYPE=$(file "$NATIVE_BINARY")
log_info "文件类型: $FILE_TYPE"
# 检查依赖
if command -v ldd &> /dev/null; then
log_info "检查动态库依赖:"
ldd "$NATIVE_BINARY" || log_warning "无法检查动态库依赖"
fi
# 快速启动测试
log_info "执行快速启动测试..."
timeout 10s "$NATIVE_BINARY" --help > /dev/null 2>&1 || log_warning "快速启动测试失败"
log_success "原生镜像验证完成"
}
# 生成构建报告
generate_report() {
log_info "生成构建报告..."
NATIVE_BINARY="$BUILD_DIR/$APP_NAME"
JAR_FILE="$BUILD_DIR/$APP_NAME-1.0.0.jar"
REPORT_FILE="$BUILD_DIR/build-report.txt"
cat > "$REPORT_FILE" << EOF
=== Spring Native 构建报告 ===
构建时间: $(date)
应用名称: $APP_NAME
主类: $MAIN_CLASS
=== 文件信息 ===
JAR 文件: $JAR_FILE
JAR 大小: $(du -h "$JAR_FILE" 2>/dev/null | cut -f1 || echo "未找到")
原生镜像: $NATIVE_BINARY
镜像大小: $(du -h "$NATIVE_BINARY" 2>/dev/null | cut -f1 || echo "未找到")
=== 系统信息 ===
操作系统: $(uname -s)
架构: $(uname -m)
Java 版本: $(java -version 2>&1 | head -n1)
GraalVM 版本: $(native-image --version 2>&1 | head -n1)
=== 构建配置 ===
优化级别: O2
垃圾收集器: G1
静态链接: 是
EOF
log_success "构建报告已生成: $REPORT_FILE"
cat "$REPORT_FILE"
}
# 主函数
main() {
log_info "开始 Spring Native 原生镜像构建流程"
check_environment
clean_build
compile_java
run_tests
package_app
build_native_image
verify_native_image
generate_report
log_success "Spring Native 原生镜像构建完成!"
log_info "可执行文件位置: $BUILD_DIR/$APP_NAME"
log_info "运行命令: ./$BUILD_DIR/$APP_NAME"
}
# 错误处理
trap 'log_error "构建过程中发生错误,退出码: $?"' ERR
# 执行主函数
main "$@"
4.2 Windows 构建脚本
# build-native.ps1
param(
[string]$AppName = "spring-native-demo",
[string]$MainClass = "com.example.demo.Application",
[string]$BuildDir = "target"
)
# 设置错误处理
$ErrorActionPreference = "Stop"
# 颜色输出函数
function Write-ColorOutput {
param(
[string]$Message,
[string]$Color = "White"
)
Write-Host $Message -ForegroundColor $Color
}
function Write-Info {
param([string]$Message)
Write-ColorOutput "[INFO] $Message" "Blue"
}
function Write-Success {
param([string]$Message)
Write-ColorOutput "[SUCCESS] $Message" "Green"
}
function Write-Warning {
param([string]$Message)
Write-ColorOutput "[WARNING] $Message" "Yellow"
}
function Write-Error {
param([string]$Message)
Write-ColorOutput "[ERROR] $Message" "Red"
}
# 检查环境
function Test-Environment {
Write-Info "检查构建环境..."
# 检查 Java
try {
$javaVersion = java -version 2>&1 | Select-String "version" | ForEach-Object { $_.ToString().Split('"')[1] }
$majorVersion = [int]$javaVersion.Split('.')[0]
if ($majorVersion -lt 17) {
throw "需要 Java 17 或更高版本,当前版本: $javaVersion"
}
Write-Success "Java 版本检查通过: $javaVersion"
}
catch {
Write-Error "Java 检查失败: $($_.Exception.Message)"
exit 1
}
# 检查 GraalVM native-image
try {
$nativeImageVersion = native-image --version 2>&1 | Select-Object -First 1
Write-Success "GraalVM native-image 检查通过: $nativeImageVersion"
}
catch {
Write-Error "GraalVM native-image 未安装或不在 PATH 中"
Write-Info "请安装 GraalVM 并运行: gu install native-image"
exit 1
}
# 检查 Maven
try {
$mavenVersion = mvn --version 2>&1 | Select-Object -First 1
Write-Success "Maven 检查通过: $mavenVersion"
}
catch {
Write-Error "Maven 未安装或不在 PATH 中"
exit 1
}
}
# 清理构建目录
function Clear-BuildDirectory {
Write-Info "清理构建目录..."
& mvn clean
if ($LASTEXITCODE -ne 0) {
throw "Maven clean 失败"
}
$nativeImageDir = Join-Path $BuildDir "native-image"
if (Test-Path $nativeImageDir) {
Remove-Item $nativeImageDir -Recurse -Force
}
New-Item -ItemType Directory -Path $nativeImageDir -Force | Out-Null
Write-Success "构建目录清理完成"
}
# 编译 Java 代码
function Build-JavaCode {
Write-Info "编译 Java 代码..."
& mvn compile
if ($LASTEXITCODE -ne 0) {
throw "Java 代码编译失败"
}
Write-Success "Java 代码编译完成"
}
# 运行测试
function Invoke-Tests {
Write-Info "运行单元测试..."
& mvn test
if ($LASTEXITCODE -ne 0) {
throw "单元测试失败"
}
Write-Success "单元测试通过"
}
# 打包应用
function Build-Package {
Write-Info "打包应用..."
& mvn package -DskipTests
if ($LASTEXITCODE -ne 0) {
throw "应用打包失败"
}
Write-Success "应用打包完成"
}
# 构建原生镜像
function Build-NativeImage {
Write-Info "开始构建原生镜像..."
$startTime = Get-Date
& mvn -Pnative native:compile
if ($LASTEXITCODE -ne 0) {
throw "原生镜像构建失败"
}
$endTime = Get-Date
$buildTime = ($endTime - $startTime).TotalSeconds
Write-Success "原生镜像构建完成,耗时: $([math]::Round($buildTime, 2))s"
# 检查生成的文件
$nativeBinary = Join-Path $BuildDir "$AppName.exe"
if (Test-Path $nativeBinary) {
$fileSize = [math]::Round((Get-Item $nativeBinary).Length / 1MB, 2)
Write-Success "原生镜像文件: $nativeBinary (大小: ${fileSize}MB)"
}
else {
throw "原生镜像文件未找到: $nativeBinary"
}
}
# 验证原生镜像
function Test-NativeImage {
Write-Info "验证原生镜像..."
$nativeBinary = Join-Path $BuildDir "$AppName.exe"
# 检查文件信息
$fileInfo = Get-Item $nativeBinary
Write-Info "文件大小: $([math]::Round($fileInfo.Length / 1MB, 2))MB"
Write-Info "创建时间: $($fileInfo.CreationTime)"
# 快速启动测试
Write-Info "执行快速启动测试..."
try {
$process = Start-Process -FilePath $nativeBinary -ArgumentList "--help" -Wait -PassThru -WindowStyle Hidden
if ($process.ExitCode -eq 0) {
Write-Success "快速启动测试通过"
}
else {
Write-Warning "快速启动测试失败,退出码: $($process.ExitCode)"
}
}
catch {
Write-Warning "快速启动测试异常: $($_.Exception.Message)"
}
Write-Success "原生镜像验证完成"
}
# 生成构建报告
function New-BuildReport {
Write-Info "生成构建报告..."
$nativeBinary = Join-Path $BuildDir "$AppName.exe"
$jarFile = Join-Path $BuildDir "$AppName-1.0.0.jar"
$reportFile = Join-Path $BuildDir "build-report.txt"
$jarSize = if (Test-Path $jarFile) { [math]::Round((Get-Item $jarFile).Length / 1MB, 2) } else { "未找到" }
$imageSize = if (Test-Path $nativeBinary) { [math]::Round((Get-Item $nativeBinary).Length / 1MB, 2) } else { "未找到" }
$report = @"
=== Spring Native 构建报告 ===
构建时间: $(Get-Date)
应用名称: $AppName
主类: $MainClass
=== 文件信息 ===
JAR 文件: $jarFile
JAR 大小: ${jarSize}MB
原生镜像: $nativeBinary
镜像大小: ${imageSize}MB
=== 系统信息 ===
操作系统: $($env:OS)
架构: $($env:PROCESSOR_ARCHITECTURE)
Java 版本: $(java -version 2>&1 | Select-Object -First 1)
GraalVM 版本: $(native-image --version 2>&1 | Select-Object -First 1)
=== 构建配置 ===
优化级别: O2
垃圾收集器: G1
静态链接: 否
"@
$report | Out-File -FilePath $reportFile -Encoding UTF8
Write-Success "构建报告已生成: $reportFile"
Write-Host $report
}
# 主函数
function Main {
try {
Write-Info "开始 Spring Native 原生镜像构建流程"
Test-Environment
Clear-BuildDirectory
Build-JavaCode
Invoke-Tests
Build-Package
Build-NativeImage
Test-NativeImage
New-BuildReport
Write-Success "Spring Native 原生镜像构建完成!"
Write-Info "可执行文件位置: $(Join-Path $BuildDir "$AppName.exe")"
Write-Info "运行命令: .\$BuildDir\$AppName.exe"
}
catch {
Write-Error "构建过程中发生错误: $($_.Exception.Message)"
exit 1
}
}
# 执行主函数
Main
通过本章的学习,你已经掌握了 Spring Native 原生镜像的构建配置和优化技巧。接下来我们将学习性能调优和监控方法。