大家好,我是R哥。

Java 24 刚发布半年左右,Java 25 又正式发布了:

上一篇:Java 24 正式发布,超神了。。。

没错,Java 版本号来到了 25,终于和 2025 年份同时命名了,Java 在发版本这条路上没有回头路了,简直超神了。。。

如何下载?

Java 25 下载地址:

https://www.oracle.com/java/technologies/downloads/

Java 25:长期支持版本

这次得说明下,Java 25 是一个长期支持的大版本,上一个长期支持的版本是 Java 21,如下表所示:

版本 发布日期 优先支持期限 延长支持期限
8 (LTS) 03/2014 03/2022 12/2030
9 – 10 (non-LTS) 09/2017 09/2018 不支持
11 (LTS) 09/2018 09/2023 01/2032
12 – 16 (non-LTS) 03/2019 09/2021 不支持
17 (LTS) 09/2021 09/2026 09/2029
18 – 20 (non-LTS) 03/2022 09/2023 不支持
21 (LTS) 09/2023 09/2028 09/2031
22 (non-LTS) 03/2024 09/2024 不支持
23 (non-LTS) 09/2024 03/2025 不支持
24 (non-LTS) 03/2025 09/2025 不支持
25 (LTS) 09/2025 09/2030 09/2033
26 (non-LTS) 03/2026 09/2026 不支持
27 (non-LTS) 09/2026 03/2027 不支持

Java 版本分为 LTS(Long-Term Support,长期支持版)Non-LTS(非长期支持版),它们的主要区别如下:

对比项 LTS 版本(长期支持) Non-LTS 版本(非长期支持)
发布周期 2 年 一次 6 个月 发布一次
支持时长 官方长期支持(8 年+) 仅支持 6 个月
适用场景 生产环境、企业级项目、长期维护的系统 个人学习、实验性项目、尝鲜新特性
稳定性 更稳定,企业级可用 新特性多,但可能不稳定
安全性 持续提供安全更新和 bug 修复 仅在生命周期内提供短期修复
新特性 主要以稳定性性能优化为主 包含最新特性,但可能在下个版本修改或移除

所以,Java 25 是可以用在企业级项目的,支持时间长达 8 年以上,因为它是稳定版本,支持的周期更长。

Java 25 新特性

JDK 25 提供了 18 项新功能:

编号 特性名称 中文解释 备注
470 PEM Encodings of Cryptographic Objects 加密对象的 PEM 编码 第一次预览
502 Stable Values 稳定值 第一次预览
503 Remove the 32-bit x86 Port 移除 32 位 x86 端口
505 Structured Concurrency 结构化并发 第五次预览
506 Scoped Values 作用域值
507 Primitive Types in Patterns, instanceof, and switch 模式匹配支持原始类型 第三次预览
508 Vector API 向量 API 第十次孵化
509 JFR CPU-Time Profiling JFR CPU 时间分析 实验特性
510 Key Derivation Function API 密钥生成函数 API
511 Module Import Declarations 模块导入声明
512 Compact Source Files and Instance Main Methods 紧凑源文件和实例主方法
513 Flexible Constructor Bodies 灵活的构造函数体
514 Ahead-of-Time Command-Line Ergonomics 预编译命令行操作优化
515 Ahead-of-Time Method Profiling 预编译方法分析
518 JFR Cooperative Sampling JFR 协同采样
519 Compact Object Headers 紧凑对象头 正式转正
520 JFR Method Timing & Tracing JFR 方法计时与跟踪
521 Generational Shenandoah Shenandoah 分代回收 正式转正

其中包括 1 个实验性特性、4 个预览特性、1 个孵化特性,不管是性能优化、语法增强、安全升级,还是工具链改进,都带来了显著的提升。

完整特性说明可以参考:

1、语言层特性

507 – Primitive Types in Patterns, instanceof, and switch

模式匹配支持原始类型,第三次预览。

模式匹配功能又升级啦,现在所有模式环境都支持基本数据类型了, instanceof 操作符和 switch 表达式及语句也进行了扩展,可以处理各种基本数据类型。

来看一个示例:

switch (x.getStatus()) {
    case 0 -> "okay";
    case 1 -> "warning";
    case 2 -> "error";
    default -> "unknown status: " + x.getStatus();
}

更多详细介绍可看这篇:

Java 14 之模式匹配,非常赞的一个新特性!

511 – Module Import Declarations

模块导入声明。

模块导入声明能简洁地导入一个模块所导出的所有包,简化了模块库的复用,且无需将导入代码置于模块内部,即导入代码本身并不需要位于一个模块中。

512 – Compact Source Files and Instance Main Methods

紧凑源文件和实例主方法。

有了紧凑源文件和实例主方法,我们可以在不需要了解面向大型程序设计的全部语言特性的情况下,就能写出第一个程序。

之前的 public static void main(String[] args) 可以简化成:

void main() {
    System.out.println("Hello, World!");
}

直接写 main 方法就能执行,类都不用写了。

另外,在 java.lang 包中添加了一个新类,使用 IO 就能打印了:

void main() {
    IO.println("Hello, World!");
}

这个简化是真牛逼,之前的 main 方法 确实受够了!!

513 – Flexible Constructor Bodies

灵活的构造函数体。

灵活的构造函数体允许在调用其他构造函数(如 super(..)this(..))之前申明其他语句,这些语句不能引用正在构造的对象实例,但可以用来初始化它的字段。

来看这个示例:

class Person {

    ...
    int age;

    Person(..., int age) {
        if (age < 0)
            throw new IllegalArgumentException(...);
        ...
        this.age = age;
    }

}

class Employee extends Person {

    private static int verifyAge(int value) {
        if (age < 18 || age > 67)
            throw new IllegalArgumentException(...);
        return value;
    }

    Employee(..., int age) {
        super(..., verifyAge(age));
    }

}

在调用其他构造函数之前先初始化字段,或者验证参数,可以让类在方法被覆盖时更可靠。

2、类库 / API 特性

470 – PEM Encodings of Cryptographic Objects

加密对象的 PEM 编码,第一次预览。

现在引入了一种 API,用于将代表加密密钥、证书和证书撤销列表的对象编码为广泛使用的隐私增强邮件(PEM)传输格式,同时也能将该格式中的内容解码回相应的对象。

这是一个 PEM 编码的密码学对象示例:

-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEi/kRGOL7wCPTN4KJ2ppeSt5UYB6u
cPjjuKDtFTXbguOIFDdZ65O/8HTUqS/sVzRF+dg7H3/tkQ/36KdtuADbwQ==
-----END PUBLIC KEY-----

一个 PEM 文本包含密钥二进制表示的 Base64 编码,并且被分别包含 BEGINEND 字样的头部和尾部包围。

502 – Stable Values

稳定值,预览特性。

Stable Values 中保存的是不可变数据,JVM 会把它们当成常量来处理,这样就能实现跟声明 final 字段一样的性能优化。

如下面的示例:

class OrderController {

    // 之前的写法:
    // private Logger logger = null;

    // 稳定值写法:
    private final StableValue<Logger> logger = StableValue.of();

    Logger getLogger() {
        return logger.orElseSet(() -> Logger.create(OrderController.class));
    }

    void submitOrder(User user, List<Product> products) {
        getLogger().info("订单已创建");
        ...
        getLogger().info("订单已完成");
    }

}

logger字段保存了一个稳定值,由 StableValue.of() 静态工厂方法创建,初始时,该稳定值未设置,即不保存任何内容,真正使用时才进行初始化。

所以,和 final 字段相比,Stable Values 在初始化时间上更加灵活,不用那么严格,可以看成是 final 的升级版,也可以和 final 一起使用。

505 – Structured Concurrency

结构化并发,第五次预览。

Structured Concurrency 是结构化并发,结构化并发的主要类是 StructuredTaskScope,位于 java.util.concurrent 包中,它能大大简化并发编程。

它允许我们将一个任务构建为一系列并发子任务,并将它们作为一个单元进行协调,子任务通过分别分叉,然后将它们合并为一个单元,在各自的线程中执行。

来看下面的示例:

Response handle() throws InterruptedException {

    try (var scope = StructuredTaskScope.open()) {

        Subtask<String> user = scope.fork(() -> findUser());
        Subtask<Integer> order = scope.fork(() -> fetchOrder());

        scope.join();   // 合并子任务,并传播异常情况

        // 这两个子任务都已完成,将它们的结果合并起来并返回。
        return new Response(user.get(), order.get());
    }

}

它把跑在不同线程里的一组相关任务看作一个整体,这样一来,错误处理和取消操作就更顺畅了,可靠性也更高,而且可观测性也得到了增强。

506 – Scoped Values

作用域值。

Scoped Values 是作用域值,它提供了一种在同一个线程内的调用者和子线程之间共享不可变数据的方法,有了它,方法就能在线程内,跟它的调用者以及子线程共享不可变数据啦。

来看下面的示例:

// 定义作用域值
static final ScopedValue<...> NAME = ScopedValue.newInstance();

// 在某些方法中
ScopedValue.where(NAME, <value>).run(() -> { ... NAME.get() ... call methods ... });

// 在直接或间接从 lambda 表达式调用的方法中
... NAME.get() ...

相比 ThreadLocal 线程本地变量,Scoped Values 更容易理解和使用。而且,当和虚拟线程以及结构化并发一起使用时,它们在空间和时间上的开销也更低。

508 – Vector API

向量 API,第十次孵化。

Vector API 能够支持可靠的向量计算,并在支持的 CPU 架构上实时编译为最优的向量指令,从而实现比等效的标量计算更出色的性能。

510 – Key Derivation Function API

密钥生成函数 API。

现在引入了一个用于密钥生成的函数 API,这玩意儿是一种密码学算法,能从一个密钥和其他数据中派生出更多的密钥。

来看下面的示例:

// 用指定的算法创建一个 KDF 对象
KDF hkdf = KDF.getInstance("HKDF-SHA256");

// 创建一个参数说明
AlgorithmParameterSpec params =
    HKDFParameterSpec.ofExtract()
                     .addIKM(initialKeyMaterial)
                     .addSalt(salt).thenExpand(info, 32);

// 生成一个 32 字节的 AES 密钥
SecretKey key = hkdf.deriveKey("AES", params);

// 可以使用相同的 KDF 对象再次调用 deriveKey 方法。
...

3、性能和运行时特性

509 – JFR CPU-Time Profiling

JFR CPU 时间分析,实验特性。

JDK Flight Recorder(JFR)现在已改进,它能在 Linux 上能收集更精确的 CPU 时间分析数据。

我们可以使用 JDK Mission Control 工具(JMC)对新的 CPU 时间采样记录生成图形化的火焰图分析时,如下图所示:

通过这个图能清楚地看到,这个程序几乎所有的 CPU 时间都花在 tenFastRequests 上了。

514 – Ahead-of-Time Command-Line Ergonomics

预编译命令行操作优化。

预编译命令行操作优化,它为 HotSpot JVM 带来了与 AOT 相关的全新优化。

它可以让预编译缓存的过程变得更简单,减少了常见使用场景下所需命令的复杂性。AOT 缓存能加快 Java 应用的启动速度,让程序运行更高效、更流畅。

515 – Ahead-of-Time Method Profiling

预编译方法分析。

预编译方法分析,能够大大缩短启动时间。

其原理是在 HotSpot Java 虚拟机启动时,立即提供之前应用程序运行时生成的方法执行分析结果。这使得即时编译器能够在应用程序启动时直接生成机器代码,从而无需在当前运行过程中等待分析数据的收集。

如下面的示例:

import java.util.*;
import java.util.stream.*;

public class HelloStreamWarmup {

    static String greeting(int n) {
        var words = List.of("Hello", "" + n, "world!");
        return words.stream()
            .filter(w -> !w.contains("0"))
            .collect(Collectors.joining(", "));
    }

    public static void main(String... args) {
        for (int i = 0; i < 100_000; i++)
            greeting(i);
        System.out.println(greeting(0));  // "Hello, world!"
    }

}

因为它使用了 Stream API,所以会加载将近 900 个 JDK 类,其中大约有 30 个热点方法会以最高优化级别进行编译。

这个程序在没有配置文件的 AOT 缓存下运行需要 90 毫秒,但收集了配置文件到 AOT 缓存之后,运行时间缩短到了 73 毫秒,性能提升了 19%!

带有配置文件的 AOT 缓存额外占用了 250 KB 的空间,大约比没有配置文件的 AOT 缓存多了 2.5%。

像这种小程序,预热时间本来就很短,但有了缓存的 profiles,再加上及时又精准的 JIT 活动,预热速度简直是如有神助,更快了。

更复杂、运行时间更长的程序,估计也能因为同样的道理,预热得更快。

518 – JFR Cooperative Sampling

JFR 协同采样。

当 JDK Flight Recorder (JFR) 以异步方式对 Java 线程栈进行采样时,其稳定性得到了提升。这是通过将调用栈遍历限制在安全点进行,同时减少安全点偏差来实现的。

519 – Compact Object Headers

紧凑对象头,正式转正。

HotSpot JVM 中对象头的大小从 96 位和 128 位减少到了 64 位,这在 64 位架构上能降低堆内存占用,提升部署密度,并增强数据局部性。

通过命令行选项启用了紧凑型对象头:

$ java -XX:+UseCompactObjectHeaders …

520 – JFR Method Timing & Tracing

JFR 方法计时与跟踪。

JDK Flight Recorder(JFR)现已支持通过字节码注入进行方法计时与追踪,对方法调用进行计时和追踪,有助于发现性能瓶颈、优化代码并找到错误的根本原因。


4、其他特性

503 – Remove the 32-bit x86 Port

移除 32 位 x86 端口。

这个 32-bit x86 端口之前在 JDK 24 中被标记为废弃,准备移除了,而且明确说了会在未来的版本中彻底移除,这次是彻底移除了,包括源代码和相关的构建支持。

521 – Generational Shenandoah

Shenandoah 是分代回收垃圾收集器,正式转正。

启用 Shenandoah 分代回收垃圾收集器:

$ java -XX:+UseShenandoahGC \
       -XX:ShenandoahGCMode=generational ...

总结

Java 25 的发布不仅是一次普通的版本升级,更是一次 里程碑式的长期支持(LTS)版本更新,支持周期长达 8 年以上,稳定性、安全性有保障,非常适合用于 企业级项目、核心系统和长期维护的服务

Java 25 是 Java 近几年最值得关注和升级的大版本。

在不久的将来,它或者会代替 Java 8 / 11 / 17 / 21,成为许多公司升级的首选目标。

可能大部分人还在用 Java 8 吧?

大家都说,你发,任你发,我用 Java 8!

看了下 newrelic 发布的最新的 Java 版本统计报告,到了 2024 年,Java 17 才是主流了

对于新项目来说,Java 17 是主流无可厚非,因为像 Spring、Spring Boot 等这样的神仙框架都已经把最低依赖升级到了 Java 17,Java 8 已经不再支持了。

所以,Java 17 是最低具备的技能了,都到了 2025 年了,如果一个程序员的知识还停留在 Java 8,那大概率说明他长时间没有学习了。

最后,推荐下我的《Java 新特性实战课》,课程非常全面,几乎覆盖了 JDK 9 ~ 17 所有核心知识点,市面上几乎没有,已全部完结,可随时报名学习全部内容。

Java 新特性课程主要以 理论 + 实战 为主,并包含必要的 原理及源码分析,提供项目完整源代码,包含以上所有知识点实战,大家可以根据课程和项目参考练习,学习起来倍轻松。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注