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 原生镜像的构建配置和优化技巧。接下来我们将学习性能调优和监控方法。