引言

Java 21 终于来了!作为自 Java 17 以来首个 LTS(长期支持)版本,Java 21 带来了众多令人期待的新特性和改进。

💡 什么是 LTS? LTS (Long-Term Support) 意味着这个版本将获得数年的官方补丁和安全更新,而不是几个月就结束支持。对于企业来说,LTS 版本是生产环境的最佳选择,也是从 Java 8 或 17 升级的最理想目标版本。

Open Liberty 作为领先的轻量级 Java 运行时,在 23.0.0.10 版本中正式添加了对 Java 21 的支持,让开发者能够在生产环境中充分体验这些新特性带来的性能提升和开发效率的改善。

本文将深入介绍 Open Liberty 23.0.0.10 对 Java 21 的支持,以及本次发布中的其他重要更新。

Open Liberty 23.0.0.10 新特性概览

在本次发布中,Open Liberty 带来了以下重要更新:

  1. Java 21 支持 – 全面支持最新的 Java LTS 版本
  2. featureUtility 命令增强 – 默认验证特性签名,提升安全性
  3. 服务器配置改进 – 支持在配置中包含指定目录的所有文件
Read more: Open Liberty 23.0.0.10 正式支持 Java 21:虚拟线程等重磅特性一览

📁 配置目录包含实战(CI/CD 利器)

“支持在配置中包含指定目录的所有文件”这个特性对 CI/CD 和配置分离 非常有用。

配置示例:

<include dir="${server.config.dir}/configDropins/defaults" />

实战场景说明:

  • 这能让运维同学通过挂载 Volume 的方式直接把多个 XML 配置文件塞进目录
  • Liberty 会自动读取目录中的所有配置文件,无需逐个写 <include>
  • 特别适合 Kubernetes/OpenShift 环境下的配置管理

快速开始:在 Open Liberty 中使用 Java 21

环境准备

要在 Open Liberty 中运行 Java 21,只需以下几个简单步骤:

  1. 下载并安装 Open Liberty 23.0.0.10 或更高版本
  2. 获取 Java 21 运行时
    • 推荐从 Adoptium 下载 Eclipse Temurin 21
  3. 配置 JAVA_HOME
    • 编辑 Open Liberty 运行时的 server.env 文件
    • 将 JAVA_HOME 指向你的 Java 21 安装目录
    • 💡 兼容性提示:Java 21 对 Jakarta EE 10 和 MicroProfile 6 提供完美的向后兼容支持,这是 Open Liberty 的一大优势
  4. 启动测试
    • 现在可以开始测试你的应用程序了!

构建工具配置

Maven 配置

在 pom.xml 中添加以下插件配置:

<plugin>
    <groupId>io.openliberty.tools</groupId>
    <artifactId>liberty-maven-plugin</artifactId>
    <version>3.8.2</version>
</plugin>

Gradle 配置

在 build.gradle 中添加:

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'io.openliberty.tools:liberty-gradle-plugin:3.6.2'
    }
}
apply plugin: 'liberty'

容器化部署

使用官方容器镜像:

FROM icr.io/appcafe/open-liberty

Java 21 核心新特性解析

Java 21 包含了从 Java 18 到 21 的所有特性更新,以下是其中的亮点:

1. 虚拟线程(Virtual Threads)- JEP 444 ⭐

这是 Java 21 中最受期待的特性!

虚拟线程是 Java 平台的一次重大革新,它旨在为高吞吐量的并发应用程序提供更好的性能。传统线程(平台线程)是操作系统线程的包装,创建和切换成本高昂。而虚拟线程是由 Java 运行时管理的轻量级线程,可以创建数百万个而不会耗尽系统资源。

适用场景:

  • 大部分时间处于阻塞状态的任务(如等待 I/O 操作)
  • 需要处理大量并发连接的微服务应用
  • 高吞吐量的 Web 应用程序

示例场景:

// 传统方式
try (var executor = Executors.newThreadPerTaskExecutor(new ThreadFactory() {
    public Thread newThread(Runnable r) { return new Thread(r); }
})) {
    IntStream.range(0, 10000).forEach(i -> {
        executor.submit(() -> {
            Thread.sleep(1000);
            return i;
        });
    });
}

// 使用虚拟线程
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    IntStream.range(0, 10000).forEach(i -> {
        executor.submit(() -> {
            Thread.sleep(1000);
            return i;
        });
    });
}

💡 注意事项:虚拟线程使用的最佳实践

虽然虚拟线程很强,但需要注意以下使用场景:

  • 适合场景I/O 密集型 任务(如等待数据库响应、HTTP 调用、文件读写)
  • 不适合场景CPU 密集型 任务(如大规模图像处理、加密计算、复杂算法)
  • 内存警告:避免使用过大的 ThreadLocal 变量,因为虚拟线程的数量可能极其庞大(百万级),会导致内存溢出
  • 调试建议:使用 JFR(Java Flight Recorder)监控虚拟线程的使用情况

📊 为什么虚拟线程能承载百万级并发?

传统线程与虚拟线程的核心差异:

graph LR
    subgraph "传统线程 (Platform Threads)"
        PT1[线程1] --> OS1[OS 线程1]
        PT2[线程2] --> OS2[OS 线程2]
        PT3[线程3] --> OS3[OS 线程3]
        Note1[创建成本高<br/>MB 级内存<br/>数千个即上限]
    end
    
    subgraph "虚拟线程 (Virtual Threads)"
        VT1[虚拟线程1] --> Carrier[载体线程]
        VT2[虚拟线程2] --> Carrier
        VT3[虚拟线程3] --> Carrier
        VT4[虚拟线程N...] --> Carrier
        Note2[创建成本低<br/>KB 级内存<br/>百万级无压力]
    end
    
    Carrier --> OS[OS 线程]
    
    style Note1 fill:#ffebee,stroke:#c62828,stroke-width:2px
    style Note2 fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px

核心原理

  • 传统线程:1 个 Java 线程 = 1 个 OS 线程(重量级,创建成本高)
  • 虚拟线程:多个虚拟线程复用少量载体线程(轻量级,按需挂载)

2. 序列化集合(Sequenced Collections)- JEP 431

为集合框架引入了统一的访问序列元素的方式:

SequencedCollection<String> seq = new ArrayList<>();
seq.addFirst("First");
seq.addLast("Last");
String first = seq.getFirst();
String last = seq.getLast();

3. Record 模式匹配(Record Patterns)- JEP 440

增强了模式匹配能力,使 Record 的解构更加简洁:

record Point(int x, int y) {}

Object obj = new Point(3, 4);
if (obj instanceof Point(int x, int y)) {
    System.out.println("x = " + x + ", y = " + y);
}

4. switch 模式匹配(Pattern Matching for switch)- JEP 441

switch 表达式支持模式匹配,代码更加简洁安全:

Object obj = "Hello";
String result = switch (obj) {
    case Integer i -> "Integer: " + i;
    case String s -> "String: " + s;
    case Point(int x, int y) -> "Point: " + x + ", " + y;
    default -> "Unknown";
};

5. 分代 ZGC(Generational ZGC)- JEP 439

ZGC 现在支持分代回收,进一步降低了延迟并提高了吞吐量,特别适合大型堆内存的应用。

6. 其他重要更新

  • JEP 400: 默认使用 UTF-8 编码
  • JEP 408: 简单 Web 服务器
  • JEP 413: Java API 文档中的代码段
  • JEP 416: 用方法句柄重新实现核心反射
  • JEP 418: 互联网地址解析 SPI
  • JEP 421: 弃用 Finalization 准备移除
  • JEP 422: Linux/RISC-V 移植
  • JEP 431: 序列化集合
  • JEP 439: 分代 ZGC
  • JEP 449: 弃用 Windows 32-bit x86 移植,准备移除
  • JEP 451: 准备禁止动态加载代理
  • JEP 452: 密钥封装机制 API

📊 Java 21 在 Open Liberty 中的架构位置

graph TD
    User((开发者)) -->|Java 21 代码| OL[Open Liberty 23.0.0.10]
    subgraph J21_Features [Java 21 特性层]
        VT[虚拟线程 - 高并发]
        SC[序列化集合]
        PM[模式匹配]
    end
    OL --> J21_Features
    J21_Features --> OS[操作系统线程/资源]
    
    style VT fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px
    style OL fill:#e3f2fd,stroke:#1565c0,stroke-width:2px
    style SC fill:#fff3e0,stroke:#e65100,stroke-width:2px
    style PM fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
    style OS fill:#efebe9,stroke:#4e342e,stroke-width:2px

featureUtility 安全性增强

在 23.0.0.10 版本中,featureUtility 命令进行了重要的安全性升级:

之前的验证方式

只验证校验和(checksum),确保文件未被篡改,但无法验证文件的真实来源。

现在的验证方式

默认启用 --verify=enforce,在下载特性时同时验证:

  • 完整性:通过校验和确保文件未被篡改
  • 真实性:通过签名验证确认特性来自 Liberty 开发团队或受信任的第三方

使用方式

# 默认行为:强制验证(推荐)
featureUtility installFeature [featureName]

# 跳过验证(仅适用于离线环境或可信内网)
# 注意:在公网环境下,强烈推荐保持默认配置以防供应链攻击
featureUtility installFeature [featureName] --verify=skip

# 或通过配置文件设置(同样仅建议在内网环境使用)
# 在 featureUtility.properties 中设置 verify=skip

⚠️ 安全提示--verify=skip 通常只在**离线环境(Air-gapped environment)**或完全可信的内部镜像站才使用。在公网环境下,强力推荐保持默认配置以防供应链攻击。

Open Liberty 开发工具支持

Open Liberty 为各大主流 IDE 提供了优秀的开发工具支持:

这些工具提供了高效的开发、测试、调试和应用程序管理功能,全部在你的 IDE 中完成!

性能提升与实际应用

虚拟线程的性能优势

根据初步测试和社区反馈,虚拟线程在以下场景中表现出显著优势:

  1. 微服务 REST API:处理大量并发请求时,响应时间更稳定
  2. 数据库访问层:等待数据库响应时不会阻塞平台线程
  3. 消息队列消费:高并发消息处理场景吞吐量提升明显

迁移建议

  1. 逐步迁移:可以先在非关键服务中尝试 Java 21
  2. 性能测试:对比虚拟线程与传统线程池的性能差异
  3. 监控工具:使用 JFR(Java Flight Recorder)监控虚拟线程的使用情况

参考资料

总结

Open Liberty 23.0.0.10 对 Java 21 的支持,为 Java 开发者带来了全新的可能性。特别是虚拟线程的引入,将极大地简化并发编程模型,提升应用程序的吞吐量和响应性能。

无论你是正在运行微服务架构,还是开发传统的企业应用,现在都是尝试 Java 21 和 Open Liberty 的最佳时机。下载最新版本,在你的应用程序中体验这些令人兴奋的新特性吧!


立即体验:

欢迎在评论区分享你使用 Java 21 虚拟线程的经验和心得!