← 返回文章列表

Java 27 新特性详解:9 个 JEP 与升级影响

JavaJVM性能安全

一句话总结

Java 27 于 2026 年 9 月 15 日正式发布(JSR 402),是 Java 25 LTS 之后的首个非 LTS 版本,一共带来 9 个 JEP。这一版没有颠覆性的新语法,重心放在三处:夯实运行时默认值(G1 成为所有环境的默认垃圾收集器、默认启用紧凑对象头)、补齐安全短板(TLS 1.3 后量子混合密钥交换默认开启),以及继续打磨一组预览与孵化特性(惰性常量、基本类型模式匹配、结构化并发、Vector API、PEM 编码)。

对还在用 Java 21 / 25 LTS 的团队,Java 27 更像一份「未来会变成什么样」的预告;但其中两项 Final 改动即使你不升级,也会在今后升级 LTS 时迎面遇到。

版本定位:非 LTS,9 个 JEP 分三类

先厘清基本盘:Oracle 每半年发一个特性版本、每两年一个 LTS。Java 21 和 Java 25 是 LTS,Java 27 不是,Oracle 会为 JDK 27 提供更新到 2027 年 3 月。生产环境仍应优先选 LTS;Java 27 更适合在测试环境提前验证新行为,或给新项目试水。

成熟度JEP含义
正式(Final)523 · 527 · 534 · 536默认生效的运行时与安全改进
预览(Preview)531 · 532 · 533 · 538需 --enable-preview 才能使用
孵化(Incubator)537Vector API 继续孵化,API 仍可能变

下面按「语言 → API → 性能 → 工具链/JVM → 废弃与移除」逐项拆解,最后给一份迁移清单。

语言层面:两个仍在预览的特性

这一版语言上没有转正的新语法,值得关注的是两个预览特性的演进。

JEP 531 · Lazy Constants(第三次预览)

它并不是一个语言级 lazy 关键字,而是一个 java.lang.LazyConstant 预览 API:声明时只提供「计算函数」,真正的初始化推迟到第一次读取时,且并发下最多执行一次、结果不可变、不允许为 null。

// 声明时不初始化,第一次 get() 才创建
private static final LazyConstant<Logger> logger =
    LazyConstant.of(() -> Logger.create(App.class));

// 懒集合:元素按需初始化
static final List<Connection> pool =
    List.ofLazy(16, _ -> new Connection());

它解决的是「大量 static final 一次性初始化拖慢启动」的问题:普通静态字段在类初始化阶段就全部求值,而懒常量把开销延后到真正用到的那一刻。若要享受 JVM 的常量折叠优化,需要把 LazyConstant 放进 final 字段(最好 static final)。JDK 27 相对 JDK 26 移除了 isInitialized()、orElse(T) 等低层方法,并补上了 Set.ofLazy(...)。

JEP 532 · 基本类型模式匹配(第五次预览)

此前 instanceof、switch 与记录模式只能匹配引用类型;这一版让 int、long、float、double、boolean 等基本类型也能参与模式匹配,核心语义是「无损转换才匹配」——如果转换会丢信息,整个模式就不匹配。

// instanceof 基本类型模式
int i = 1000;
if (i instanceof byte b) { /* 不匹配:1000 超出 byte 范围 */ }

// switch 支持 long / boolean,并可用 when 加守卫
switch (status) {
    case 0                   -> "ok";
    case int n when n >= 100 -> "high";
    case int n               -> "unknown: " + n;
}

// 记录模式里嵌套基本类型模式
record JsonNumber(double d) {}
if (json instanceof JsonNumber(int age)) { /* 仅当 double 能无损转 int */ }

这消除了大量「先手动强转、再做范围检查」的样板代码,让 switch 也能直接处理 long、boolean 与浮点选择器。注意浮点 case 常量必须与选择器类型一致(float 选择器要用 0f 而非 0),否则编译报错。

API 更新:并发、矢量与加密

这一版没有新的转正 API,但有四个 API 处于预览/孵化阶段持续推进,外加若干正式小更新。

  • 结构化并发(JEP 533,第七次预览):StructuredTaskScope 把一组相关任务当作一个工作单元统一管理,父子任务的异常传播、取消与可观测性更清晰,是虚拟线程之后并发模型的重要拼图。仍属预览,接口尚未定型。
  • Vector API(JEP 537,第十二次孵化):面向 SIMD 的矢量计算 API,可编译为 CPU 向量指令,适合数值密集场景;因为长期孵化,API 会变,不建议生产依赖。
  • PEM 编码(JEP 538,第三次预览):为证书、密钥等加密对象提供标准 PEM 格式的读取与输出能力,减少手写「BEGIN/END」解析的胶水代码。
  • 后量子混合密钥交换(JEP 527,正式):TLS 1.3 新增 X25519MLKEM768、SecP256r1MLKEM768、SecP384r1MLKEM1024 混合算法组并默认启用,把抗量子算法与传统算法结合,抵御「现在窃取、将来解密」的攻击。

正式的小更新包括:KeyStore.getCreationInstant(String) 返回条目创建时间;FFM API 支持在 downcall 前初始化线程局部执行状态;新增 jdk.security.password.allowSystemIn 等安全属性与 HSS/LMS 签名参数集。

性能优化:G1 一统与紧凑对象头

两项 Final 改动会影响每一个 Java 应用。

  • JEP 523 · G1 全环境默认:G1 成为所有环境(包括此前默认 Serial GC 的客户端/小内存场景)的默认垃圾收集器,统一了默认行为。同时 G1 的 MinHeapFreeRatio/MaxHeapFreeRatio 默认值改为 0/100,默认不再因这些约束做堆的缩容抖动。
  • JEP 534 · 紧凑对象头:64 位架构上对象头从 96 位降到 64 位(类指针始终压缩),堆越小、小对象越多的应用省得越明显。与之配套,UseCompressedClassPointers 被标记为 obsolete——类指针现在始终压缩,设置该选项会被忽略并告警。

对绝大多数应用,这两项默认开启通常都是「白拿」的收益;需要留意的是依赖了对象头布局、或做堆外/字节码改写这类非常规操作的库。

工具链与 JVM 调整

  • JFR 进程内数据脱敏(JEP 536,正式):默认对命令行参数、环境变量、系统属性初始值做脱敏,降低把密钥等敏感信息写进 JFR 记录的风险;新增 redact-key、redact-argument 选项,jdk.SystemProcess 事件也不再输出命令行参数。
  • jcmd 增强:新增 Bash 自动补全,以及 VM.security_properties 命令查看运行中 JVM 的安全属性;VM.info 与 fatal error log 会报告打开的文件描述符数。
  • AOT 模式:新增 -XX:AOTMode=required(on 的别名,将来会替代 on)。
  • TLS 细节:TLS 1.3 证书压缩(zlib)默认开启;ffdhe6144、ffdhe8192 从默认命名组中移除。

废弃与移除:升级前必须核对

这是迁移时最需要逐条比对的部分。

已移除

  • ThreadPoolExecutor.finalize()(此前已废弃)
  • JVMCI:jdk.internal.vm.ci、jdk.graal.compiler 等模块及相关标志
  • 启动器选项 -noclassgc、-noverify、-verifyremote、-Xverify:none
  • Linux 的 VFORK 进程启动机制、Serviceability Agent 的 printmdo 命令
  • java.locale.useOldISOCodes 系统属性(旧 ISO 语言代码不再生效)

已废弃 / 行为变化

  • -XX:InitiatingHeapOccupancyPercent 更名为 -XX:G1IHOP(旧名保留为别名)
  • LDAP 服务提供者不再默认设置三个 JNDI 标准属性;HttpServer 由字符串前缀匹配改为路径前缀匹配
  • ML-KEM / ML-DSA 私钥默认编码改为 seed,与旧 JDK 存在互操作影响
  • TimeZone.getDefault() 在 Windows 上返回最新 IANA ID(如 Asia/Kolkata);ServiceLoader 遇 linkage error 统一抛 ServiceConfigurationError

迁移检查清单

  1. 先确认是否值得升:生产环境优先 Java 21 / 25 LTS;若只是想验证新行为,用测试环境跑 Java 27 即可。
  2. 预览特性显式开启:用到 JEP 531/532/533/538 时,编译和运行都要带 --enable-preview。
  3. 扫描已移除项:全局搜索 ThreadPoolExecutor.finalize、旧启动参数、Graal/JVMCI 依赖;如有第三方库依赖 JVMCI,先确认替代方案。
  4. 核对 GC 与对象头假设:确认没有代码或监控脚本依赖旧默认 GC 或对象头布局。
  5. 关注加密互操作:若与旧版本交换 ML-KEM/ML-DSA 私钥,注意默认编码已改为 seed。
  6. 跑全量测试:重点覆盖序列化、时区、启动参数、TLS 握手这几类容易踩坑的场景。

未来趋势展望

把 Java 27 放进更大的时间轴看,几个长期项目正在逼近:Project Valhalla(值类型,减少指针跳跃与装箱开销)、Project Leyden(启动性能与预热优化)、以及后量子密码的持续演进。结构化并发与 Vector API 的反复预览,也说明 Java 在并发与数值计算两条线上仍会继续打磨。Java 27 的价值不在「多了一个语法糖」,而在于它把一批即将成为默认的行为提前交到开发者手里。

总结

Java 27 是一个「打地基」的版本:G1 与紧凑对象头默认化直接作用于运行时的每一字节,后量子 TLS 默认开启则把安全水位整体抬高一档;语言与 API 上则以预览/孵化为主,面向愿意尝鲜的团队。对大多数开发者,这一版最重要的动作不是升级,而是读懂那两张「已移除」与「行为变化」的清单,为将来升级到下一个 LTS 做好预案。