前置知识: Java

Java 新特性与生态

00:00
8 min Advanced 2026/6/14

Java 21-24 新特性、模块系统、Spring Boot 3.x、构建工具与 GraalVM 原生镜像。

1. Java 21-24 新特性概览

Java 自从切换到六个月发布周期后,每个 LTS 版本都带来了重要的语言和运行时改进。Java 21 是最新的 LTS 版本,Java 22 和 23 持续引入预览特性,Java 24 进一步巩固了这些改进。

版本发布时间LTS关键特性
Java 212023-09Virtual Threads、Record Patterns、Pattern Matching for switch
Java 222024-03Unnamed Variables & Patterns、Stream Gatherers(预览)
Java 232024-09Primitive Types in Patterns(预览)、Module Import Declarations
Java 242025-03Stream Gatherers(正式)、Compact Object Headers

1.1 Virtual Threads(虚拟线程)

虚拟线程是 Project Loom 的核心成果,在 Java 21 中正式发布。它是一种轻量级线程,由 JVM 而非操作系统管理,使得创建百万级线程成为可能。

// 传统平台线程 —— 每个线程占用约 1MB 栈空间
try (var executor = Executors.newFixedThreadPool(200)) {
    IntStream.range(0, 10_000).forEach(i -> {
        executor.submit(() -> {
            Thread.sleep(Duration.ofSeconds(1));
            return i;
        });
    });
} // 200 个线程处理 10000 个任务,需要排队

// 虚拟线程 —— 几乎无限制的并发
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    IntStream.range(0, 1_000_000).forEach(i -> {
        executor.submit(() -> {
            Thread.sleep(Duration.ofSeconds(1));
            return i;
        });
    });
} // 百万级虚拟线程同时运行

关键注意事项:

  • 避免在虚拟线程中使用 synchronized,应改用 ReentrantLock(即”固定”问题)
  • 虚拟线程适用于 I/O 密集型任务,不适用于 CPU 密集型计算
  • 使用 Thread.ofVirtual().name("my-vthread").start(runnable) 自定义虚拟线程
// 使用 ReentrantLock 替代 synchronized
private final ReentrantLock lock = new ReentrantLock();

public void safeMethod() {
    lock.lock();
    try {
        // 临界区逻辑
    } finally {
        lock.unlock();
    }
}

1.2 Record Patterns(记录模式)

Record Patterns 在 Java 21 正式发布,允许在 instanceofswitch 中解构记录类:

record Point(int x, int y) {}
record Rectangle(Point upperLeft, Point lowerRight) {}

// instanceof 解构
if (obj instanceof Point(int x, int y)) {
    System.out.println("x = " + x + ", y = " + y);
}

// 嵌套解构
if (obj instanceof Rectangle(Point(int x1, int y1), Point(int x2, int y2))) {
    System.out.printf("矩形: (%d,%d) -> (%d,%d)%n", x1, y1, x2, y2);
}

// switch 中使用 Record Patterns
static String describeShape(Object shape) {
    return switch (shape) {
        case Point(int x, int y) when x == y -> "对角线上的点";
        case Point(int x, int y) -> "普通点 (%d, %d)".formatted(x, y);
        case Rectangle(Point ul, Point lr) -> "矩形";
        default -> "未知形状";
    };
}

1.3 Pattern Matching for switch

Java 21 正式发布了 switch 的模式匹配,结合 Record Patterns 和 Guarded Patterns 提供了强大的模式匹配能力:

static String formatObject(Object obj) {
    return switch (obj) {
        case Integer i when i > 0  -> "正整数: %d".formatted(i);
        case Integer i             -> "非正整数: %d".formatted(i);
        case String s              -> "字符串(长度%d): %s".formatted(s.length(), s);
        case int[] arr             -> "int数组(长度%d)".formatted(arr.length);
        case null                  -> "null 值";
        default                    -> "其他类型: " + obj.getClass().getSimpleName();
    };
}

1.4 Sequenced Collections

Java 21 引入了 SequencedCollectionSequencedSetSequencedMap 接口,统一了有序集合的访问方式:

// 之前:不同集合获取首尾元素的方式不同
list.get(0);                // List
list.get(list.size() - 1);
deque.getFirst();           // Deque
deque.getLast();
sortedSet.first();          // SortedSet
sortedSet.last();

// 现在:统一接口
sequencedCollection.getFirst();
sequencedCollection.getLast();
sequencedCollection.reversed(); // 返回逆序视图

// SequencedMap
sequencedMap.firstEntry();
sequencedMap.lastEntry();
sequencedMap.reversed();
sequencedMap.sequencedEntrySet();
sequencedMap.sequencedValues();

1.5 String Templates(预览)

Java 21 引入了字符串模板的预览特性(注意:在后续版本中仍在演进):

// 使用 STR 模板处理器
String message = STR."欢迎 \{name},你的余额为 \{balance} 元";

// 自定义模板处理器
var JSON = StringTemplate.RAW;
StringTemplate template = JSON."""
    {
        "name": "\{name}",
        "age": \{age}
    }
    """;

1.6 Unnamed Patterns & Variables

Java 22 正式引入了未命名模式和变量:

// 未命名变量 —— 不需要的返回值
try {
    int result = riskyOperation();
} catch (Exception _) {  // 不需要异常对象
    log.error("操作失败");
}

// 未命名模式 —— 忽略 Record 中的某些组件
if (obj instanceof Point(int x, _)) {
    System.out.println("x = " + x); // 只关心 x
}

// switch 中的未命名模式
switch (shape) {
    case Rectangle(Point(int x, _), _) -> "矩形宽度: " + x;
    case Circle(_) -> "圆形";
}

2. Java 模块系统(JPMS)

Java 9 引入的模块系统(Project Jigsaw)在 Java 21+ 中已成为成熟特性。模块系统通过 module-info.java 显式声明依赖和导出,解决了 classpath 的脆弱性问题。

2.1 模块定义

// src/com.example.app/module-info.java
module com.example.app {
    requires com.example.service;      // 声明依赖
    requires transitive com.example.util; // 传递依赖
    exports com.example.app.api;       // 导出包
    exports com.example.app.spi to com.example.impl; // 限定导出
    opens com.example.app.model to com.fasterxml.jackson.databind; // 反射访问
    uses com.example.service.Processor; // 声明服务消费
    provides com.example.service.Processor  // 声明服务提供
        with com.example.app.DefaultProcessor;
}

2.2 模块路径 vs 类路径

特性ClasspathModule Path
可靠性脆弱,容易冲突可靠,显式声明依赖
封装性所有 public 类都可访问只有 exports 的包可访问
启动速度较慢,需扫描所有 JAR较快,按需加载模块
反射访问无限制需要 opens 声明

2.3 实际迁移策略

# 使用 jdeps 分析依赖
jdeps --module-path mods -s myapp.jar

# 使用 jlink 创建自定义运行时
jlink --module-path mods \
      --add-modules com.example.app \
      --output custom-runtime \
      --strip-debug \
      --compress zip-6 \
      --no-header-files \
      --no-man-pages

3. Spring Boot 3.x 核心

Spring Boot 3.x 基于 Spring Framework 6,要求 Java 17+,全面拥抱 Jakarta EE 10 规范。

3.1 自动配置原理

Spring Boot 的自动配置基于 @Conditional 系列注解和 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件:

// 自定义自动配置类
@AutoConfiguration
@ConditionalOnClass(DataSource.class)
@ConditionalOnMissingBean(DataSource.class)
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceAutoConfiguration {

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource dataSource(DataSourceProperties props) {
        return DataSourceBuilder.create()
            .url(props.getUrl())
            .username(props.getUsername())
            .password(props.getPassword())
            .build();
    }
}
# META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
com.example.config.DataSourceAutoConfiguration

3.2 Spring Boot Actuator

Actuator 提供生产级别的监控和管理端点:

# application.yml
management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,prometheus,env,beans
  endpoint:
    health:
      show-details: when-authorized
  metrics:
    export:
      prometheus:
        enabled: true
  info:
    env:
      enabled: true
    java:
      enabled: true
    os:
      enabled: true
// 自定义 Health Indicator
@Component
public class DatabaseHealthIndicator extends AbstractHealthIndicator {

    private final DataSource dataSource;

    public DatabaseHealthIndicator(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    @Override
    protected void doHealthCheck(Health.Builder builder) throws Exception {
        try (Connection conn = dataSource.getConnection()) {
            if (conn.isValid(1)) {
                builder.up().withDetail("database", "PostgreSQL")
                        .withDetail("validationQuery", "isValid()");
            }
        }
    }
}

3.3 Spring Security 6.x

Spring Security 6 全面采用组件化配置,废弃了 WebSecurityConfigurerAdapter

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/api/public/**").permitAll()
                .requestMatchers("/api/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated()
            )
            .oauth2ResourceServer(oauth2 -> oauth2
                .jwt(jwt -> jwt
                    .jwtAuthenticationConverter(jwtAuthenticationConverter())
                )
            )
            .sessionManagement(session -> session
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            );
        return http.build();
    }

    @Bean
    public JwtAuthenticationConverter jwtAuthenticationConverter() {
        JwtAuthenticationConverter converter = new JwtAuthenticationConverter();
        converter.setJwtGrantedAuthoritiesConverter(jwt -> {
            List<String> roles = jwt.getClaimAsStringList("roles");
            return roles.stream()
                .map(role -> new SimpleGrantedAuthority("ROLE_" + role))
                .collect(Collectors.toList());
        });
        return converter;
    }
}

4. 构建工具

4.1 Gradle 现代 Java 项目

Gradle 使用 Kotlin DSL 已成为主流选择:

// build.gradle.kts
plugins {
    java
    id("org.springframework.boot") version "3.3.0"
    id("io.spring.dependency-management") version "1.1.5"
}

group = "com.example"
version = "1.0.0"

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21)
    }
}

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-web")
    implementation("org.springframework.boot:spring-boot-starter-data-jpa")
    testImplementation("org.springframework.boot:spring-boot-starter-test")
}

tasks.test {
    useJUnitPlatform()
    jvmArgs = listOf("--enable-preview")  // 启用预览特性
}

// GraalVM 原生镜像插件
plugins {
    id("org.graalvm.buildtools.native") version "0.10.2"
}

4.2 Maven Central 发布

发布到 Maven Central 需要 Sonatype 账号和 GPG 签名:

// build.gradle.kts — 发布配置
publishing {
    publications {
        create<MavenPublication>("mavenJava") {
            from(components["java"])
            pom {
                name.set("My Library")
                description.set("A useful library")
                url.set("https://github.com/example/my-lib")
                licenses {
                    license {
                        name.set("Apache-2.0")
                        url.set("https://opensource.org/licenses/Apache-2.0")
                    }
                }
                developers {
                    developer {
                        id.set("fanquanpp")
                        name.set("Fan Quan")
                    }
                }
                scm {
                    url.set("https://github.com/example/my-lib")
                }
            }
        }
    }
}

signing {
    sign(publishing.publications["mavenJava"])
}

5. JPackage 打包

jpackage 工具可以将 Java 应用打包为平台原生安装包:

# 打包为 Windows 安装程序
jpackage \
  --name MyApp \
  --input target/libs \
  --main-jar myapp.jar \
  --main-class com.example.Main \
  --type msi \
  --app-version 1.0.0 \
  --vendor "Example Corp" \
  --win-dir-chooser \
  --win-menu \
  --win-shortcut \
  --java-options "--enable-preview"

# 打包为 macOS dmg
jpackage \
  --name MyApp \
  --input target/libs \
  --main-jar myapp.jar \
  --main-class com.example.Main \
  --type dmg \
  --app-version 1.0.0 \
  --vendor "Example Corp" \
  --mac-package-identifier com.example.myapp

# 打包为 Linux deb
jpackage \
  --name myapp \
  --input target/libs \
  --main-jar myapp.jar \
  --main-class com.example.Main \
  --type deb \
  --app-version 1.0.0 \
  --vendor "Example Corp"

结合 jlink 可以创建不含完整 JRE 的轻量安装包:

# 先用 jlink 创建自定义运行时
jlink --module-path target/modules \
      --add-modules com.example.app \
      --output target/custom-jre \
      --strip-debug --compress zip-6 \
      --no-header-files --no-man-pages

# 再用 jpackage 基于自定义运行时打包
jpackage \
  --name MyApp \
  --runtime-image target/custom-jre \
  --input target/libs \
  --main-jar myapp.jar \
  --main-class com.example.Main \
  --type app-image

6. GraalVM 原生镜像

GraalVM 的 Native Image 技术可以将 Java 应用编译为独立的原生可执行文件,显著提升启动速度和降低内存占用。

6.1 基本使用

# 安装 GraalVM
sdk install java 21-graal
sdk use java 21-graal

# 安装 native-image
gu install native-image

# 编译原生镜像
native-image -jar myapp.jar myapp

# 带优化的编译
native-image \
  --initialize-at-build-time \
  --no-fallback \
  -H:+ReportExceptionStackTraces \
  -H:Name=myapp \
  -jar myapp.jar

6.2 Spring Boot 原生镜像

Spring Boot 3.x 对 GraalVM 原生镜像提供了一等支持:

# 使用 Spring Boot Maven 插件
mvn -Pnative native:compile

# 使用 Spring Boot Gradle 插件
gradle nativeCompile

# 使用 buildpacks(无需本地安装 GraalVM)
mvn -Pnative spring-boot:build-image
// Runtime Hints —— 为反射、代理等提供元数据
@Configuration
@ImportRuntimeHints(MyHints.class)
public class NativeConfig {}

class MyHints implements RuntimeHintsRegistrar {
    @Override
    public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
        hints.reflection()
            .registerType(MyModel.class, MemberCategory.INVOKE_PUBLIC_METHODS)
            .registerType(MyModel.class, MemberCategory.DECLARED_FIELDS);

        hints.resources()
            .registerPattern("com/example/templates/*");

        hints.serialization()
            .registerType(MySerializable.class);

        hints.proxies()
            .registerJdkProxy(MyInterface.class);
    }
}

6.3 性能对比

指标传统 JVMGraalVM Native Image
启动时间1-3 秒10-50 毫秒
首次请求延迟JIT 预热)立即响应
内存占用200-500 MB30-80 MB
峰值吞吐量JIT 优化后)较低(AOT 限制
生态兼容性完全兼容部分反射需配置

适用场景: 容器微服务、Serverless 函数、CLI 工具、需要快速启动的云原生应用

不适用场景:时间的重计算服务(JIT峰值性能更优)、重依赖反射动态代理的遗留应用

7. 小结

Java 21+ 的新特性正在从本上改变 Java 的编程范式:

  • Virtual Threads 让 Java 回归”一请求线程”的简单模型
  • Pattern Matching条件逻辑更加声明式安全
  • Record Classes + Sealed Classes 构建了代数数据类型的基础
  • JPMS 提供了强封装和可靠的依赖管理
  • GraalVM Native Image 让 Java 在云原生场景中更具竞争力
  • Spring Boot 3.x拥抱现代 Java 特性提供开发体验

这些特性组合在一起,使得 Java 在保持向后兼容的同时,不断进化以适应现代软件开发的需求

知识检测

学习进度

-- 已学文档
--% 知识覆盖率

学习推荐

专注模式