JDK27正式发布,人麻了!

前言

2026年9月15日,Oracle正式发布了JDK 27,对应JSR 402,是Java SE 27的参考实现。

说实话,每次Java发布新版本,我都会习惯性看一眼JEP列表,然后判断“这个版本值不值得升级”。

很多版本是“预览版加预览版”,真正能落到生产环境的东西不多。

但JDK 27不太一样。

它包含9项足以单独成为JEP的增强,其中4项是预览功能、1项是孵化器功能。

更重要的是,其中有几项是默认行为变更——也就是说,你什么都不做,升级JDK就能受益。

今天这篇文章,我就把JDK 27的核心变化从头到尾给你拆解一遍。

希望对你会有所帮助。

一、JDK 27到底变了什么?

在深入每个特性之前,我先用一张表帮你建立整体认知。

JEP编号 特性名称 类型 核心影响
JEP 523 G1成为所有环境的默认GC 正式 启动更快,延迟更低
JEP 534 紧凑对象头成为默认 正式 对象头从96位降到64位
JEP 527 TLS 1.3后量子混合密钥交换 正式 默认启用,无需改代码
JEP 531 惰性常量(第三预览) 预览 AI/数据应用的性能优化
JEP 532 原始类型模式匹配(第五预览) 预览 switch/instanceof支持int/long等
JEP 533 结构化并发(第七预览) 预览 并发编程更简单、更可靠
JEP 537 Vector API(第十二孵化) 孵化 AI推理/科学计算向量加速
JEP 536 JFR进程内数据脱敏 正式 敏感信息自动脱敏
JEP 538 PEM编码API(第三预览) 预览 密钥/证书编解码标准化

这9项JEP,我按“对普通开发者影响程度”从高到低排列,逐一拆解。

二、G1成为所有环境的默认GC

这是最大的变化。

有些小伙伴在工作中可能遇到过这样的场景:写了个小工具、跑了个批处理脚本,启动的时候发现用的是Serial GC——单线程回收,启动快但一旦数据量上来就卡得不行。你以为是代码问题,其实是GC选错了。

从JDK 9开始,G1就已经是服务器环境的默认GC。

但如果你在一个内存受限的环境里跑Java——比如小容器、嵌入式设备、或者一个简单的命令行工具——JVM会默认选择Serial GC

Serial GC的问题很明显:单线程,Full GC时会长时间停顿

在小内存场景下,你可能感觉不到;但一旦数据量稍微大一点,停顿时间就会变得不可接受。

JDK 27的JEP 523把这件事改了:G1成为所有环境的默认GC,不再区分服务器和受限环境

2.1 为什么敢这么做?

Oracle在JEP里给出了明确的理由:经过这些年的持续优化,G1在所有指标上都已经和Serial持平了

具体来说:

吞吐量:JDK 27中减少了G1的同步开销(JEP 522),G1的最大吞吐量已经接近Serial。

延迟:G1在老年代回收时走的是增量回收,而不是Serial那种全量回收,所以最大延迟一直比Serial好。

原生内存:最近几个版本把G1的原生内存占用降到了和Serial相当的水平。

启动时间:在小堆场景下,G1的启动开销已经优化到不再明显。

2.2 对你意味着什么?

什么都不用改

你升级到JDK 27,不指定GC参数,JVM自动用G1。

如果你之前在小内存环境里被Serial GC的Full GC停顿折磨过,升级JDK 27后这个问题会自动消失。

当然,如果你需要极致启动速度,仍然可以显式指定Serial:-XX:+UseSerialGC

但默认情况下,G1已经是更好的选择。

三、紧凑对象头成为默认

对象头从96位砍到64位。

这是另一个默认行为变更,而且是“悄悄生效”的那种。

3.1 对象头里到底存了什么?

Java对象在堆里是怎么存的?

每个对象都有一个“对象头”,里面至少包含Mark WordKlass Pointer两部分。

在64位JVM上,传统布局是:

  • Mark Word:64位(哈希码、GC年龄、锁状态等)
  • Klass Pointer:64位(指向类元数据)

对象头总共96位,也就是12字节

加上对象体,一个最简单的new Object(),在64位JVM上实际占用16字节(对象头12字节 + 对齐填充4字节)。

3.2 紧凑对象头怎么做的?

JEP 534把Klass Pointer从64位压缩到了32位,对象头总共变成64位,即8字节

为什么能压缩?

因为JVM的类元数据空间(Metaspace)通常不会超过4GB(32位地址空间足够寻址)。

Klass Pointer其实只需要存一个索引,不需要完整的64位地址。

效果new Object()从16字节降到12字节(8字节对象头 + 4字节对齐填充)。堆占用直接减少25%

3.3 为什么这很重要?

堆占用减少25%,意味着:

  • 同样的内存能装更多对象
  • GC压力更小(对象少了,扫描和回收的负担就小了)
  • 数据局部性更好(对象更紧凑,CPU缓存命中率更高)

对于大规模Java应用——特别是那些创建大量小对象的场景——这是一个实打实的性能提升

紧凑对象头从JDK 24开始就是可选功能,经过两个版本的验证,JDK 27正式把它设为默认。

和G1一样,你不需要做任何事,升级就生效

四、TLS 1.3后量子混合密钥交换

为“量子时代”提前上锁。

“量子计算离我还远着呢,跟我有什么关系?”

这个问题我被问过不止一次。我的回答是:等量子计算能破解RSA的那一天,你今天的加密数据可能已经被存了好几年了。

攻击者的策略叫“先存后破”——现在把加密流量存下来,等量子计算机成熟了再解密。所以后量子加密不是“未来的事”,是“现在就要做的事”。

4.1 JEP 527做了什么?

JDK 27为TLS 1.3引入了后量子混合密钥交换算法

所谓“混合”,就是把抗量子算法传统算法结合起来——即使量子计算破解了传统算法那一半,抗量子算法那一半仍然安全。

新增的算法包括:

  • X25519MLKEM768(默认组列表中优先级最高)
  • SecP256r1MLKEM768
  • SecP384r1MLKEM1024

4.2 关键点:默认启用,无需改代码

如果你用的是javax.net.ssl API,升级JDK 27后,这些算法默认就会生效,不需要修改任何代码。

这意味着:你现有的HTTPS通信,在升级JDK 27后,自动获得了后量子加密保护

五、惰性常量

它是AI和数据应用的性能利器。

惰性常量(Lazy Constants)是第三次预览了,但这个特性的价值值得反复说。

5.1 它解决什么问题?

Java里传统的static final常量在类加载时就必须初始化。

如果你的常量需要昂贵的计算——比如从数据库加载配置、解析一个大文件、初始化一个ML模型——那类加载就会变得很慢。

惰性常量允许你延迟初始化,而且JVM会把它当成真正的常量来优化——性能等价于final字段。

5.2 代码示例

// 传统的static final——类加载时就得算
public static final List<Config> CONFIGS = loadFromDatabase();

// 惰性常量——用到的时候才算
private static final LazyConstant<List<Config>> CONFIGS = 
    LazyConstant.of(() -> loadFromDatabase());

// 第一次调用时初始化,之后直接走缓存
public List<Config> getConfigs() {
    return CONFIGS.get();
}

为什么这跟AI有关?

因为AI应用里大量存在这种场景——模型权重、tokenizer词表、向量索引,都是初始化昂贵但后续只读的数据。

惰性常量让这些数据可以按需加载,同时不牺牲运行时的性能。

六、原始类型模式匹配

switch终于支持int了。

这是第五次预览,但每预览一次,就离正式版更近一步。

6.1 解决了什么痛点?

以前的switch只能匹配引用类型(String、enum、包装类)。

你要匹配int,只能用传统的switch-case,没法用模式匹配的威力。

JEP 532允许原始类型用于模式匹配、instanceofswitch

6.2 代码对比

// 以前:int匹配只能这样写
switch (statusCode) {
    case 200:
        return "OK";
    case 404:
        return "Not Found";
    default:
        return "Unknown";
}

// JDK 27预览:可以用模式匹配了
Object obj = getStatusCode();
return switch (obj) {
    case int i when i == 200 -> "OK";
    case int i when i == 404 -> "Not Found";
    case String s -> "String: " + s;
    default -> "Unknown";
};

同时,这个JEP还加强了switch的支配性检查,让编译器能在编译期发现更多错误。

七、结构化并发

结构化并发第七次预览了。

虽然还是预览,但它的思路值得每个Java开发者关注。

7.1 传统并发的问题

// 传统写法:两个任务并发,但错误处理一团糟
Future<User> userFuture = executor.submit(() -> fetchUser(id));
Future<Order> orderFuture = executor.submit(() -> fetchOrder(id));

try {
    User user = userFuture.get();
    Order order = orderFuture.get();
    return new Result(user, order);
} catch (Exception e) {
    // 一个失败了,另一个还在跑,怎么取消?
    // 线程泄漏怎么办?
    throw e;
}

问题在于:这两个任务的生命周期没有和父任务绑定

父任务失败了,子任务可能还在跑;子任务失败了,父任务不知道该怎么取消另一个。

7.2 结构化并发的写法

try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
    Supplier<User> user = scope.fork(() -> fetchUser(id));
    Supplier<Order> order = scope.fork(() -> fetchOrder(id));
    
    scope.join();           // 等待所有子任务
    scope.throwIfFailed();  // 任一失败则抛出
    
    return new Result(user.get(), order.get());
}
// 离开try块时,scope自动关闭,所有未完成的子任务自动取消

核心价值:子任务的生命周期严格嵌套在父任务内。父任务失败,子任务全部取消;子任务失败,父任务感知并处理。没有线程泄漏,没有孤儿任务。

八、Vector API

它是AI推理的加速器。

Vector API第十二次孵化了。

虽然还在孵化阶段,但它在AI推理和科学计算领域的价值已经非常明确。

Vector API允许开发者在支持的CPU上利用SIMD指令——一条指令同时处理多个数据。

对于矩阵运算、向量相似度计算这类AI推理中高频出现的操作,性能提升可以是数量级的

// 向量加法——一次处理多个float
FloatVector a = FloatVector.fromArray(SPECIES, arr1, i);
FloatVector b = FloatVector.fromArray(SPECIES, arr2, i);
FloatVector c = a.add(b);
c.intoArray(result, i);

如果你的AI应用跑在支持AVX-512或ARM SVE的CPU上,Vector API能把这些硬件的向量计算能力直接暴露给Java代码

九、其他值得关注的改进

除了9项JEP,JDK 27还有几十项非JEP改进:

JEP 536:JFR进程内数据脱敏——JDK Flight Recorder在记录离开进程前,对命令行参数、环境变量和系统属性进行脱敏。生产环境做性能分析时,不会再意外泄露密钥。

ML-KEM/ML-DSA私钥编码更新——后量子密码算法的密钥编码标准化,X25519和Ed25519性能提升。

JSON线程转储——线程转储中的线程标识、线程数和进程标识改为JSON数字,监控工具解析更方便。

jcmd VM.security_properties——新增命令,可在运行时查看活动的安全属性。

移除JVMCI——部分旧选项和功能被移除。

十、优缺点

优点

1. G1全场景默认,小内存环境不再受Serial GC折磨
吞吐量、延迟、内存占用、启动时间全面持平甚至优于Serial,默认用G1是更安全的选择。

2. 对象头砍到64位,堆占用降低25%
同样的内存能装更多对象,GC压力更小,数据局部性更好。大规模应用直接受益

3. 后量子加密默认启用,无需改代码
javax.net.ssl的应用自动获得抗量子攻击能力。这是安全层面的基础性升级

4. 惰性常量为AI/数据应用优化
模型权重、向量索引等昂贵初始化数据可以按需加载,运行时性能等价于final

5. 结构化并发让并发编程更可靠
子任务生命周期严格嵌套,没有线程泄漏,没有孤儿任务。

6. JFR数据脱敏,生产环境更安全
性能分析时不会意外泄露密钥和环境变量。

注意事项

1. 非LTS版本,生产环境需谨慎
JDK 27不是LTS,Oracle更新到2027年3月。生产环境建议用JDK 25 LTS。

2. 预览/孵化特性需要--enable-preview
惰性常量、原始类型模式匹配、结构化并发、Vector API都需要显式启用预览标志,且可能与未来版本不兼容。

3. JVMCI被移除
如果你用了Graal JIT编译器(基于JVMCI),需要确认兼容性。

4. 紧凑对象头可能影响某些诊断工具
依赖对象头布局的工具(如某些Profiler)可能需要更新。

十一、适用场景

场景 推荐程度 理由
尝鲜/学习/个人项目 ✅✅✅ 强烈推荐 默认变更直接体验,预览特性可以提前探索
小内存容器/嵌入式 ✅✅✅ 强烈推荐 G1默认+紧凑对象头,启动和内存都受益
大规模Java应用 ✅✅ 推荐 堆占用降低25%,但需评估非LTS风险
安全敏感应用(HTTPS) ✅✅✅ 强烈推荐 后量子加密默认启用,零代码改动
AI/数据密集型应用 ✅✅ 推荐 惰性常量+Vector API,但预览特性需评估
需要长期稳定支持的生产环境 ⚠️ 需评估 JDK 25 LTS更稳妥
依赖Graal JIT的项目 ❌ 不推荐 JVMCI被移除,需等待GraalVM跟进

十二、写在最后

回到最初的问题:JDK 27值不值得升级?

我的判断是:值得尝鲜,但生产环境等JDK 28或JDK 29 LTS更稳妥。

JDK 27最大的价值不在于某个“炫酷的新语法”,而在于三个默认行为变更

G1成为全场景默认——你什么都不做,启动更快、延迟更低。

对象头砍到64位——你什么都不做,堆占用降25%。

后量子加密默认启用——你什么都不做,HTTPS通信就获得了抗量子保护。

这三件事加起来,是实打实的运行时收益,不是“预览版的预览版”。

预览特性里,结构化并发惰性常量是最值得关注的。

结构化并发如果转正,会改变Java并发编程的写法;惰性常量如果转正,会成为AI应用的标配。

JDK 27不是LTS,如果你现在的生产环境跑在JDK 21或JDK 25 LTS上,不用急着升

但如果你在开发新项目、跑实验环境、或者想提前感受Java的演进方向——JDK 27值得下载跑一跑

参考资源:

posted @ 2026-09-17 13:24  苏三说技术  阅读(17)  评论(0)    收藏  举报