现代 Java 新特新
编辑
前言
Java 8 自 2014 年 3 月18 日发布至今(2023), 这么多年过去了依然是国内使用最广泛的 JDK 版本, 正所谓 "他发任他发, 我用 Java 8", 突出一个稳字啊! 先来康一康 Java SE RoadMap:

Java 8 之后的10年里 Oracle 先后发布了13个版本, 其中3个 LTS 版本, 从里面的 Release 的功能可以看出来 Java 一直紧跟时代, 变化非常大, 总的来说就是迈向更轻(体积), 更快(性能), 更小(内存占用). 作为一个有灵魂码农, 也不能落后, 可以不用, 但不能不了解.
关于 Java 8 的介绍可以看我的老文章: Java8 Noob Tutorial
Java 9 - 11
Java 9
主要语言变化
新增
模块化系统(Module System): JSR 376
Project Jigsaw 的一部分
按需加载, 解决臃肿
module-info.java通过
exports,requires关键字声明作用域(感觉像 nodejs?)
新版本定义机制:
$MAJOR.$MINOR.$SECURITY.$PATCH
更新
try-with-resources语法允许变量使用 final 修饰, 语法升级diamond语法允许匿名类(如果类型推断的参数类型可表示的话)接口允许定义
private方法@SafeVarargs允许声明在实例 private 方法上
主要 API 变化
引入
进程(Process): JEP 102, 全新 API
ProcessHandle提供更好的管控操作系统内存(Memory): JEP 193,
VarHandle作为正式 API 替代Unsafe, 对变量执行原子和内存屏障操作日志(Logging): JEP 264, 全新日志 API 和服务
现在基本都用 Slf4j 了吧...
XML: JEP 268, 添加标准的 XML Catalog API
栈(Stack): JEP 259, 全新栈跟踪工具,
StackWalker替代老的StackTraceElement体系
更新
字符串(String): JEP 254, String 底层存储从
char[]替换为byte[]内存优化, 时间换空间
集合(Collections): JEP 269, 集合接口提供便利的工厂方法, 如,
Set.of(...)并发(Concurrency): JEP 266,
CompletableFuture以及其他并发组件提升Reactive Streams:
java.util.concurrent.Flow
编译器(Compiler): JEP 274, 提升
MethodHandle通用性以及更好地编译优化MethodHandle以及其他反射方式性能对比: Java Reflection, but Faster
注解(Annotation): JEP 277,
@Deprecated注解增加since和forRemoval属性, 丰富 API 淘汰策略线程(Threading): JEP 285, 新增自选方法
Thread.onSpinWait对象序列化(Serialization): JEP 290, 新增 API
ObjectInputFilter过滤ObjectInputStreamXML: JEP 255, 更新 Xerces 2.11.0 解析 XML
Java Management Extensions (JMX): 支持远程诊断命令
脚本(Scripting):
国际化(Internationalization):
Java Database Connectivity (JDBC):
JDBC-ODBC 桥接移除
JDBC 4.2 升级
主要 JVM 变化
新增
更新
垃圾回收(Garbage Collection)
移除组合:
并发标记和清扫(Concurrent Mark Sweep Collector) CMS: JEP 291
DefNew + CMS
ParNew + SerialOld
Incremental CMS
Garbage-First(G1): JEP 248: Make G1 the Default Garbage Collector
提升可读性和性能优化
标记为默认 GC
统一 JVM 日志: JEP 158
输入/输出(I/O):
减少
<JDK_HOME>/jre/lib/charsets.jar 文件大小
性能提升(Performance)
java.lang.String字节数组性能优化
工具(Tools)
Java 10
主要语言变化
新增
本地变量类型推断: JEP 286: Local-Variable Type Inference
用 var 来声明变量, 相关阅读: Java 10 新特性之局部变量类型推断
主要 API 变化
更新
通用: Optional 新增方法
orElseThrow()方法来在没有值时抛出指定的异常
集合增强
List,Set,Map提供了静态方法copyOf()返回入参集合的一个不可变拷贝
java.util.stream.Collectors中新增了静态方法, 用于将流中的元素收集为不可变的集合Collectors.toUnmodifiableList(),Collectors.toUnmodifiableSet()安全(Security):
JEP 319, 默认根证书
主要 JVM 变化
新增
JIT Compiler: JEP 317 实验性的 Java 编写的 JIT Compiler, Graal
更新
垃圾回收(Garbage Collection)
Garbage-First(G1): 并行 Full GC 支持
JEP 304: Garbage Collector Interface
内存(Memory): 运行 JVM Heap 在用户可选的设备上分配, 如: NV-DIMM
应用层级的 CDS: JEP 310: Application Class-Data Sharing
线程(Threading): JEP 312 Thread-Local Handshakes
工具(Tools)
javah: JEP 313 被移除
国际化(Internationalization): 增加 Unicode 语言 Tag 扩展
版本发布: JEP 322, 基于时间发布版本信息
Java 11(LTS)
主要语言变化
新增
字节码(Byte-code):
基于嵌套类型访问控制(JEP 181: Nest-Based Access Control)
新增常量池形式: CONSTANT_Dynamic(JEP 309: Dynamic Class-File Constants)
Lambda 参数局部变量语句: JEP 323: Local-Variable Syntax for Lambda Parameters
可以在 Lambda 表达式中使用 var
主要 API 变化
引入
HTTP: 新增 HTTP 客户端(JEP 321: HTTP Client (Standard))
更新
Optional 增强
新增了
isEmpty()方法来判断指定的Optional对象是否为空
String 增强
新增了
isBlank,strip,repeat,lines等方法
国际化(Internationalization):
Unicode 10 支持(JEP 327: Unicode 10)
安全(Security):
与 Curve25519 和 Curve448 的关键协议(JEP 324: Key Agreement with Curve25519 and Curve448)
Chacha20 和 Poly1305 加密算法(JEP 329: ChaCha20 and Poly1305 Cryptographic Algorithms)
TLS 1.3 支持(JEP 332: Transport Layer Security (TLS) 1.3)
移除 Java EE 和 CORBA 模块(JEP 320: Remove the Java EE and CORBA Modules)
java.xml.ws (JAX-WS, SAAJ and Web Services Metadata)
java.xml.bind (JAXB)
java.activation (JAF)
java.xml.ws.annotation (Common Annotations)
java.corba (CORBA)
java.transaction (JTA)
主要 JVM 变化
新增
JIT Compiler: JEP 317 实验性的 Java 编写的 JIT Compiler
垃圾回收(Garbage Collection)
工具
Java Fight Recorder(JEP 328: Flight Recorder)
java 命令直接启动单个 Java 源文件(JEP 330: Launch Single-File Source-Code Programs)
java helloword.java类脚本, 无需预先编译, 直接运行, 比如写个简单的爬虫
低消耗 JVM Heap Profiling(JEP 331: Low-Overhead Heap Profiling)
更新
内存(Memory): 运行 JVM Heap 在用户可选的设备上分配, 如: NV-DIMM
应用层级的 CDS: JEP 310
Class-Data Sharing
工具(Tools)
不推荐 JavaScript 引擎 Nashorn(JEP 335: Deprecate the Nashorn JavaScript Engine)
不推荐 Pack200 工具(JEP 336: Deprecate the Pack200 Tools and API)
GUI:
移除 Java Applet
移除 Java Web Start
移除 JavaFX
指令: 提升 Aarch64 内联函数(JEP 315: Improve Aarch64 Intrinsics)
Java 12 - 17
Java 12
主要语言变化
新增
[预览] Switch 语句优化(JEP 325: Switch Expressions (Preview))
主要 API 变化
String新增了indent方法处理缩进Files新增了mismatch来对比两个文件NumberFormat新增了对复杂的数字进行格式化的支持:getCompactNumberInstance
主要 JVM 变化
新增
单一 AArch64 端口(JEP 340: One AArch64 Port, Not Two)
默认 CDS 归档(JEP 341: Default CDS Archives)
垃圾回收(Garbage Collection)
[实验性] Shenandoah GC(JEP 189: Shenandoah: A Low-Pause-Time Garbage Collector (Experimental))
Microbenchmark 套件(JEP 230: Microbenchmark Suite)
更新
垃圾回收(Garbage Collection)
Garbage First(G1)
Java 13
主要语言变化
新增
[预览] Switch 语句优化更新(JEP 354: Switch Expressions (Preview))
新增
yield关键字
[预览] 文件块(JEP 355: Text Blocks (Preview))
主要 API 变化
更新
网络(Network): 重新实现 Socket API(JEP 353: Reimplement the Legacy Socket API)
虚拟线程铺垫
主要 JVM 变化
更新
垃圾回收(Garbage Collection)
ZGC
返回未提交内存(JEP 351: ZGC: Uncommit Unused Memory)
Java 14
主要语言变化
新增
[预览] instanceof 语句优化(JEP 305: Pattern Matching for instanceof (Preview))
在
instanceof块中转换变量
[预览] 文件块更新, 引入了两个新的转义字符 (JEP 368: Text Blocks (Second Preview))
\: 表示行尾, 不引入换行符\s: 表示单个空格
[预览] Record 类型(JEP 359: Records (Preview))
Immutable data
record Person(String name, Long id){}
Switch 语句优化(转正)(JEP 361: Switch Expressions (Standard))
主要 API 变化
引入
[孵化] 外部内存访问 API(JEP 370: Foreign-Memory Access API (Incubator))
主要 JVM 变化
更新
非 volatile 内存 ByteBuffer 映射(JEP 352: Non-Volatile Mapped Byte Buffers)
空指针异常内容辅助(JEP 358: Helpful NullPointerExceptions)
补充异常信息, 比如:
Cannot read field 'c' because 'a.b' is null.
垃圾回收(Garbage Collection)
ZGC
支持 macOS(JEP 364: ZGC on macOS)
支持 Windows(JEP 365: ZGC on Windows)
CMS
Garbage First(G1)
NUMA 架构内存分配(JEP 345: NUMA-Aware Memory Allocation for G1)
工具
JFR 流(JEP 349: JFR Event Streaming)
[孵化] 打包工具(JEP 343: Packaging Tool (Incubator))
移除 Pack200(JEP 367: Remove the Pack200 Tools and API)
Java 15
主要语言变化
引入
文本块(JEP 378: Text Blocks)
为框架(frameworks)所设计的, 隐藏类不能直接被其他类的字节码使用, 只能在运行时生成类并通过反射间接使用它们
更新
[预览] Sealed 类(JEP 360: Sealed Classes (Preview))
解决被
final修饰的类不能被继承的尴尬
[预览] instanceof 语句优化(JEP 375: Pattern Matching for instanceof (Second Preview))
[预览] Record 类型(JEP 384: Records (Second Preview))
主要 API 变化
引入
[孵化] 外部内存访问 API(JEP 383: Foreign-Memory Access API (Second Incubator))
更新
网络(Network): 重新实现 Socket API(JEP 353: Reimplement the Legacy Socket API)
Remote Method Invocation(RMI): JEP 385: Deprecate RMI Activation for Removal
主要 JVM 变化
更新
移除 Solaris 和 SPARC JVM 实现(JEP 381: Remove the Solaris and SPARC Ports)
线程(Threading)
失效和不推荐使用偏向锁(JEP 374: Disable and Deprecate Biased Locking)
偏向锁的引入增加了 JVM 的复杂性大于其带来的性能提升
垃圾回收(Garbage Collection)
工具
移除 Nashorn JavaScript 引擎(JEP 372: Remove the Nashorn JavaScript Engine)
安全(Security):
Java 16
主要语言变化
引入
Record 类型正式引入(JEP 395: Records)
instanceof 语句优化正式引入(JEP 394: Pattern Matching for instanceof)
更新
Stream 新增
toList()方法, 直接可转换成不可变的 Listlist.stream().toList()
模块化(Modular): JDK 内部 API 默认强封装(JEP 396: Strongly Encapsulate JDK Internals by Default)
[孵化] 向量 API(JEP 338: Vector API (Incubator))
API 将使开发人员能够轻松地用 Java 编写可移植的高性能向量算法
[预览] Sealed 类(JEP 397: Sealed Classes (Second Preview))
引入
网络(Network):
Unix-Domain Socket(JEP 380: Unix-Domain Socket Channels)
Native:
[孵化] 替代 JNI Java API: JEP 389: Foreign Linker API (Incubator)
[孵化] 外部内存访问 API(JEP 393: Foreign-Memory Access API (Third Incubator))
通用: 单个 API 应该能够对各种外部内存(如本机内存、持久内存、堆内存等)进行操作.
安全: 无论操作何种内存, API 都不应该破坏 JVM 的安全性.
控制: 可以自由的选择如何释放内存(显式、隐式等).
可用: 如果需要访问外部内存, API 应该是
sun.misc.Unsafe.
主要 JVM 变化
引入
源码(SourceCode):
激活 C++ 14 特性(JEP 347: Enable C++14 Language Features)
迁移到 Git 上(JEP 357: Migrate from Mercurial to Git)
在此之前, OpenJDK 源代码是使用版本管理工具 Mercurial 进行管理, 现在迁移到了 Git
Alpine Linux 实现(JEP 386: Alpine Linux Port)
Windows/AArch64 实现(JEP 388: Windows/AArch64 Port)
更新
垃圾回收(Garbage Collection)
ZGC
工具(Tools)
jpackage 容器打包工具(JEP 392: Packaging Tool)
Java 17(LTS)
主要语言变化
引入
Sealed 类正式引入(JEP 409: Sealed Classes)
sealed: 修饰类/接口, 用来描述这个类/接口为密封类/接口non-sealed: 修饰类/接口, 用来描述这个类/接口为非密封类/接口permits: 用在extends和implements之后, 指定可以继承或实现的类
浮点数: 浮点数默认
strictfp(JEP 306: Restore Always-Strict Floating-Point Semantics)
更新
模块化(Modular): JDK 内部 API 强封装(JEP 403: Strongly Encapsulate JDK Internals)
[预览] Switch 语句增强模式匹配(JEP 406: Pattern Matching for switch (Preview))
类似
instanceof的匹配+转换:case Integer i -> String.format("int %d", i);
[孵化] 向量 API(JEP 414: Vector API (Second Incubator))
主要 API 变化
引入
[孵化] 外部 Native 函数和内存 API(JEP 412: Foreign Function & Memory API (Incubator))
关联:
更新
工具(Utility): Random 增强(JEP 356: Enhanced Pseudo-Random Number Generators)
安全(Security):
不推荐 SecurityManager, 未来将移除(JEP 411: Deprecate the Security Manager for Removal)
Remote Method Invocation(RMI): 移除 RMI Activation(JEP 407: Remove RMI Activation)
对象序列化(Serialization): 上下文反序列化过滤器(JEP 415: Context-Specific Deserialization Filters)
用户界面(UI):
Applet: 不推荐使用, 未来移除(JEP 398: Deprecate the Applet API for Removal)
主要 JVM 变化
引入
源码(SourceCode):
macOS/AArch64 支持(JEP 391: macOS/AArch64 Port)
更新
工具(Tools):
移除实验性 AOT 和 JIT 编译器(JEP 410: Remove the Experimental AOT and JIT Compiler), 由 GraalVM 替代
用户界面(UI):
新 macOS 渲染引擎(JEP 382: New macOS Rendering Pipeline)
Java 18 - 21
Java 18
主要语言变化
更新
[孵化] 向量 API JEP 417: Vector API (Third Incubator)
[预览]
switch语句模式匹配 JEP 420: Pattern Matching for switch (Second Preview)默认字符集为 UTF-8 JEP 400:UTF-8 by Default
主要 API 变化
更新
[孵化] 外部 Native 函数和内存 API JEP 419: Foreign Function & Memory API (Second Incubator)
输入/输出(I/O):
UTF-8 作为默认字符 JEP 400: UTF-8 by Default
反射(Reflection):
基于
MethodHandlers重新实现核心反射API JEP 416: Reimplement Core Reflection with Method Handles
网络(Network):
简单 Web Server JEP 408: Simple Web Server
主要 JVM 变化
更新
不推荐 Finalization, 未来删除 JEP 421: Deprecate Finalization for Removal
工具(Tools)
javadoc: API 文档增加代码片段 JEP 413: Code Snippets in Java API Documentation
使用姿势:
{@snippet : System.out.print("a");}
Java 19
主要语言变化
更新
[预览] Record 模式(JEP 405: Record Patterns (Preview))
[预览] 虚拟线程(JEP 425: Virtual Threads (Preview))
[预览]
switch语句模式匹配(JEP 427: Pattern Matching for switch (Third Preview))[孵化] 向量 API(JEP 426: Vector API (Fourth Incubator))
主要 API 变化
更新
[预览] 外部 Native 函数和内存 API(JEP 424: Foreign Function & Memory API (Preview))
[孵化] 结构化并发(JEP 428: Structured Concurrency (Incubator))
StructuredTaskScope
主要 JVM 变化
引入
源码(SourceCode):
Linux/RISC 支持(JEP 422: Linux/RISC-V Port)
Java 20
主要语言变化
引入
[预览] 虚拟线程(JEP 436: Virtual Threads (Second Preview))
[孵化] 作用域值(JEP 429: Scoped Values (Incubator))
[预览] Record 模式(JEP 432: Record Patterns (Second Preview))
[预览]
switch语句模式匹配(JEP 433: Pattern Matching for switch (Fourth Preview))[孵化] 向量 API(JEP 438: Vector API (Fifth Incubator))
主要 API 变化
更新
[预览] 外部 Native 函数和内存 API(JEP 434: Foreign Function & Memory API (Second Preview))
[孵化] 结构化并发(JEP 437: Structured Concurrency (Second Incubator))
Java 21(LTS)
主要语言变化
引入
虚拟线程(JEP 444: Virtual Threads)
Record 模式(JEP 440: Record Patterns)
switch语句模式匹配(JEP 441: Pattern Matching for switch)[预览] String 模板(JEP 430: String Templates (Preview))
[预览] 未命名模式和变量(JEP 443: Unnamed Patterns and Variables (Preview))
[预览] 未命名类和实例 main 方法(JEP 445: Unnamed Classes and Instance Main Methods (Preview))
[预览] 作用域值(JEP 446: Scoped Values (Preview))
更新
[孵化] 向量 API(JEP 448: Vector API (Sixth Incubator))
主要 API 变化
引入
集合(Collections): 有序集合(JEP 431: Sequenced Collections)
安全(Security): Key 封装 API(JEP 452: Key Encapsulation Mechanism API)
更新
[预览] 外部 Native 函数和内存 API(JEP 442: Foreign Function & Memory API (Third Preview))
[预览] 结构化并发(JEP 453: Structured Concurrency (Preview))
主要 JVM 变化
更新
垃圾回收(Garbage Collection)
分代 ZGC(JEP 439: Generational ZGC)
目前默认关闭, 未来会设置成默认, 可以通过配置打开:
-XX:+UseZGC -XX:+ZGenerational
源码(SourceCode):
移除 Windows 32 位 x86 实现(JEP 449: Deprecate the Windows 32-bit x86 Port for Removal)
预备禁止动态 Agent 加载(JEP 451: Prepare to Disallow the Dynamic Loading of Agents)
Java 22 - 25
Java 21 作为上一个 LTS 版本于 2023 年 9 月发布, 随后 Oracle 按照半年一版的节奏又接连推出了 JDK 22、23、24, 直到 2025 年 9 月, 新一代 LTS JDK 25 正式到来. 这四个版本延续了 Java 迈向 更轻、更快、更易用 的趋势, 核心主题包括:
Project Loom 的收尾: 虚拟线程彻底解除
synchronized钉扎限制Project Amber 的丰收: Unnamed Variables、Stream Gatherers、Flexible Constructor Bodies 等语言特性相继转正
Project Panama 落地: Foreign Function & Memory API 正式取代 JNI
Project Leyden 启航: AOT 类加载/链接让 Spring PetClinic 启动提速 42%
后量子密码: ML-KEM、ML-DSA 两大算法入驻标准库
低碳 JVM: 紧凑对象头 (Compact Object Headers) 降低堆内存 22%
Java 22
发布日期: 2024 年 3 月 19 日
主要语言变化
新增
匿名变量与匿名模式(Unnamed Variables & Patterns): JEP 456 — 正式版
用下划线
_作为占位符声明 "不打算使用" 的变量或模式适用场景:
catch参数、Lambda 参数、for-each循环变量、解构模式中的无关组件消除静态分析工具对 "未使用变量" 的误报, 使意图更加明确
// 循环中不关心循环变量 for (Order _ : orders) total++; // catch 不需要异常对象 try { int i = Integer.parseInt(s); } catch (NumberFormatException _) { System.out.println("Bad number: " + s); } // Lambda 参数忽略 stream.collect(Collectors.toMap(String::toUpperCase, _ -> "NODATA")); // 解构模式中忽略无关字段 if (r instanceof ColoredPoint(Point(int x, int y), _)) { System.out.println(x + ", " + y); }构造函数体前置语句(Statements before
super(...)): JEP 447 — 预览版允许在显式构造函数调用
super(...)或this(...)之前插入语句前置语句不能引用
this, 但可以初始化字段、做参数校验从根本上解决了 "子类构造时无法提前校验入参" 的老大难问题 (详见 JDK 25 正式转正)
更新
隐式声明类与实例 main 方法(Implicitly Declared Classes and Instance Main Methods): JEP 463 — 第二次预览
继续打磨降低入门门槛的语法糖, 允许省略
public static void main(String[])中的修饰符允许
main()写成实例方法, 省略public、static及String[]参数
字符串模板(String Templates): JEP 459 — 第二次预览
允许使用模板处理器(如
STR、FMT)生成字符串, 比字符串拼接更安全、更有表达力⚠️ 注意: 该特性在 JDK 23 时被撤回, 设计团队认为需要更多时间重新设计 API
主要 API 变化
引入
外部函数与内存 API(Foreign Function & Memory API): JEP 454 — 正式版
历经 JDK 19(JEP 424)、20(JEP 434)、21(JEP 442) 三轮预览后终于转正
提供纯 Java API 调用原生库 / 操作堆外内存, 彻底替代脆弱的 JNI 和危险的
sun.misc.Unsafe核心 API:
MemorySegment(内存段)、Arena(生命周期管理)、Linker(函数链接)、SymbolLookup(符号查找)性能与 JNI 相当甚至更优, 且保证无 use-after-free 内存安全
// 调用 C 标准库的 radixsort 函数 Linker linker = Linker.nativeLinker(); SymbolLookup stdlib = linker.defaultLookup(); MethodHandle radixsort = linker.downcallHandle(stdlib.find("radixsort").get(), ...); try (Arena offHeap = Arena.ofConfined()) { MemorySegment pointers = offHeap.allocate(ValueLayout.ADDRESS, 4); // ... 填充数据并调用 radixsort.invoke(pointers, 4, MemorySegment.NULL, '\0'); }
预览/孵化
Stream 收集器(Stream Gatherers): JEP 461 — 第一次预览
为 Stream API 增加自定义中间操作
Stream::gather(Gatherer), 与Stream::collect(Collector)对终止操作的关系类似支持一对一、一对多、多对一、多对多的元素转换, 以及短路操作和并行化
结构化并发(Structured Concurrency): JEP 462 — 第二次预览
作用域值(Scoped Values): JEP 464 — 第二次预览
类文件 API(Class-File API): JEP 457 — 第一次预览
提供标准 API 用于解析、生成和转换
.class字节码文件, 取代第三方库如 ASM
主要 JVM 变化
新增
G1 区域钉扎(Region Pinning for G1): JEP 423
JNI 临界区(Critical Regions)期间 G1 不再需要暂停 GC, 降低 JNI 调用的延迟抖动
多文件源码程序启动(Launch Multi-File Source-Code Programs): JEP 458
java命令现在可以直接运行由多个.java文件组成的小程序, 无需先javac编译适合脚本场景和快速原型
# 直接运行多文件程序 java Main.java Helper.java Utils.java
孵化
向量 API(Vector API): JEP 460 — 第七次孵化
持续在各平台(x64 AVX、AArch64 NEON)打磨 SIMD 向量计算 API
Java 23
发布日期: 2024 年 9 月 17 日
主要语言变化
新增(预览)
模式中的原始类型(Primitive Types in Patterns, instanceof, and switch): JEP 455 — 第一次预览
将模式匹配扩展到所有原始类型(
int、long、double等)instanceof和switch可以直接对原始类型做模式匹配
// switch 直接匹配原始类型 switch (x) { case int i when i > 0 -> System.out.println("positive: " + i); case int i -> System.out.println("non-positive: " + i); } // instanceof 检查原始类型范围 if (i instanceof byte b) { // 如果 i 能无损转换为 byte // 使用 b }模块导入声明(Module Import Declarations): JEP 476 — 第一次预览
新增
import module M;语法, 一次导入整个模块导出的所有包import module java.base;等价于 54 个包的按需导入, 大幅减少 import 模板代码
import module java.base; // 一行替代 java.util.*, java.util.stream.*, java.io.* 等 54 个包 // 现在可以直接使用 List, Map, Stream, Path 等 var fruits = List.of("apple", "berry", "citrus"); var result = Stream.of(fruits).collect(Collectors.joining(", "));
更新(预览)
构造函数体前置语句: JEP 482 — 第二次预览 (改名自 JEP 447)
隐式声明类与实例 main 方法: JEP 477 — 第三次预览
Stream Gatherers: JEP 473 — 第二次预览
结构化并发: JEP 480 — 第三次预览
作用域值: JEP 481 — 第三次预览
类文件 API: JEP 466 — 第二次预览
主要 API 变化
更新
工具(Tools):
Markdown 文档注释(Markdown Documentation Comments): JEP 467
JavaDoc 注释现在支持 CommonMark Markdown 语法, 用
///三斜杠开头代替传统的/** */用
code替代{@code}, 用[链接]替代{@link}, 用- item替代<li>极大提升文档注释的可读性和编写体验
// 传统风格 /** * Returns a hash code value for the object. * <ul> * <li>If two objects are equal, their hash codes must be equal.</li> * </ul> * @return a hash code value * @see Object#equals(Object) */ // Markdown 风格 (JDK 23+) /// Returns a hash code value for the object. /// /// - If two objects are equal, their hash codes must be equal. /// /// @return a hash code value /// @see Object#equals(Object)
废弃
sun.misc.Unsafe内存访问方法废弃: JEP 471标记
sun.misc.Unsafe中的内存访问方法为@Deprecated(forRemoval=true)替代方案:
VarHandle(JDK 9)和 Foreign Function & Memory API(JDK 22 正式版)
主要 JVM 变化
更新
垃圾回收(Garbage Collection)
ZGC 分代模式设为默认(ZGC: Generational Mode by Default): JEP 474
ZGC 的分代模式(JDK 21 引入)在经过充分验证后成为默认配置
分代 ZGC 通过分别维护新生代和老年代对象, 降低了内存消耗并提升了吞吐量
老的非分代模式仍可通过
-XX:ZGCGenerations=0临时使用, 但已标记废弃
孵化
向量 API: JEP 469 — 第八次孵化
Java 24
发布日期: 2025 年 3 月 18 日
主要语言变化
新增(预览)
原始类型模式: JEP 488 — 第二次预览
灵活构造函数体: JEP 492 — 第三次预览
模块导入声明: JEP 494 — 第二次预览
简单源文件与实例 main 方法: JEP 495 — 第四次预览
主要 API 变化
正式转正
Stream 收集器(Stream Gatherers): JEP 485 — 正式版
历经 JDK 22(JEP 461)、23(JEP 473) 两轮预览后转正
Stream::gather(Gatherer)成为标准 API, 支持任意自定义中间操作java.util.stream.Gatherers提供内置工厂方法:fold、scan、windowFixed、windowSliding、mapConcurrent
// 滑动窗口: 每3个元素一组 Stream.of(1, 2, 3, 4, 5) .gather(Gatherers.windowSliding(3)) .toList(); // => [[1, 2, 3], [2, 3, 4], [3, 4, 5]] // 自定义: 按字符串长度去重 stream.gather(Gatherer.ofSequential( HashSet::new, (seen, element, downstream) -> { if (seen.add(element.length())) downstream.push(element); return true; } ));类文件 API(Class-File API): JEP 484 — 正式版
JDK 官方提供标准的字节码操作 API(
java.lang.classfile包), 替代 ASM 等第三方库JDK 内部工具(javac、反射等)已迁移到该 API 上
引入
抗量子 ML-KEM 密钥封装机制(Quantum-Resistant Module-Lattice-Based Key Encapsulation Mechanism): JEP 496
基于 NIST FIPS 203 标准实现 ML-KEM(前身 Kyber), 抵御量子计算机的 Shor 算法攻击
支持三种参数集: ML-KEM-512、ML-KEM-768(默认)、ML-KEM-1024
提供
KeyPairGenerator、KEM、KeyFactory的 ML-KEM 实现
// 生成密钥对 KeyPairGenerator g = KeyPairGenerator.getInstance("ML-KEM"); g.initialize(NamedParameterSpec.ML_KEM_768); KeyPair kp = g.generateKeyPair(); // 发送方: 封装密钥 KEM kem = KEM.getInstance("ML-KEM"); KEM.Encapsulator enc = kem.newEncapsulator(kp.getPublic()); KEM.Encapsulated encap = enc.encapsulate(); byte[] msg = encap.encapsulation(); // 发送给接收方 // 接收方: 解封装 KEM.Decapsulator dec = kem.newDecapsulator(kp.getPrivate()); SecretKey sharedKey = dec.decapsulate(msg);抗量子 ML-DSA 数字签名算法(Quantum-Resistant Module-Lattice-Based Digital Signature Algorithm): JEP 497
基于 NIST FIPS 204 标准实现 ML-DSA(前身 Dilithium), 替代 RSA 等传统签名算法
支持三种参数集: ML-DSA-44、ML-DSA-65、ML-DSA-87
预览
主要 JVM 变化
新增
AOT 类加载与链接(Ahead-of-Time Class Loading & Linking): JEP 483
来自 Project Leyden, 通过 "训练运行 → 创建缓存 → 使用缓存" 三步流程将类的加载/链接工作提前完成
HelloStream 程序(~600 个 JDK 类): 启动时间从 31ms 降至 18ms, 提升 42%
Spring PetClinic(~21,000 个类): 启动时间从 4.486s 降至 2.604s, 同样提升 42%
# Step 1: 训练运行, 记录 AOT 配置 java -XX:AOTMode=record -XX:AOTConfiguration=app.aotconf -cp app.jar com.example.App # Step 2: 创建 AOT 缓存 java -XX:AOTMode=create -XX:AOTConfiguration=app.aotconf -XX:AOTCache=app.aot -cp app.jar # Step 3: 使用缓存运行 java -XX:AOTCache=app.aot -cp app.jar com.example.App虚拟线程无钉扎同步(Synchronize Virtual Threads without Pinning): JEP 491
彻底解决 JDK 21 虚拟线程中
synchronized方法/块导致虚拟线程被 "钉扎" 在平台线程上的问题改造 JVM 的 monitor 实现, 使
synchronized能追踪虚拟线程而非底层平台线程进入
synchronized时如需阻塞, 虚拟线程可正常 unmount, 释放平台线程给其他虚拟线程现有代码无需改动即可享受虚拟线程的高扩展性, 无需再将
synchronized替换为ReentrantLock
紧凑对象头(Compact Object Headers): JEP 450 — 实验性
来自 Project Lilliput, 将对象头从 96/128 位压缩至 64 位
SPECjbb2015: 堆内存减少 22%, CPU 时间减少 8%, GC 次数减少 15%
通过
-XX:+UnlockExperimentalVMOptions -XX:+UseCompactObjectHeaders开启 (JDK 25 转为正式特性)
分代 Shenandoah GC(Generational Shenandoah): JEP 404 — 实验性
Shenandoah 增加分代支持, 分别处理新生代与老年代, 进一步降低停顿时间
更新
垃圾回收(Garbage Collection)
安全(Security)
限制 JNI 使用准备(Prepare to Restrict the Use of JNI): JEP 472
未来版本将对未授权的 JNI 使用发出限制警告, 与 FFM API 的管控模型对齐
移除
移除 Windows 32 位 x86 端口: JEP 479
彻底删除 Windows 32 位 x86 平台的 JVM 移植代码
Java 25(LTS)
发布日期: 2025 年 9 月 16 日 | 长期支持版本 (LTS)
Java 25 是继 Java 21 之后的下一个 LTS 版本, 收录了 JDK 22-24 中孵化的众多特性, 同时延续了性能与可观测性方向的深耕.
主要语言变化
正式转正
紧凑源文件与实例 main 方法(Compact Source Files and Instance Main Methods): JEP 512
历经 JDK 21-24 四轮预览后终于在 JDK 25 LTS 中转正
两大核心简化:
实例 main 方法:
main()可省略public、static和String[]参数紧凑源文件: 可以省略外层
class声明, 直接写方法体
新增
java.lang.IO工具类, 提供IO.println()替代System.out.println()紧凑源文件自动导入
java.base及其他常用标准模块
// Hello World 的终极简化版(JDK 25 正式版) void main() { IO.println("Hello, World!"); }// 可以同时声明字段和方法, 无需 class 关键字 String greeting = "Hello"; void main() { IO.println(greeting + ", World!"); printList(List.of("Java", "Go", "Rust")); } void printList(List<String> list) { list.forEach(IO::println); }模块导入声明(Module Import Declarations): JEP 511 — 正式版
import module M;语法正式转正, 一行导入整个模块的所有导出包import module java.base;替代 54 个import语句,import module java.sql;自动传递依赖包同名类冲突时, 用更具体的单类型导入覆盖解决
灵活构造函数体(Flexible Constructor Bodies): JEP 513 — 正式版
super()/this()之前可以写任意不访问this的语句允许在调用父类构造之前校验参数、初始化子类字段
解决了 "父类构造调用子类重写方法时子类字段未初始化" 的安全漏洞
class Employee extends Person { String officeID; Employee(int age, String officeID) { // JDK 25 之前: 必须先 super(), 无法提前校验 // JDK 25+: 可以先校验再 super(), 甚至先初始化 officeID if (age < 18 || age > 67) throw new IllegalArgumentException("Age out of range: " + age); this.officeID = officeID; // 在 super() 前初始化, 防止父类构造访问到 null super(age); } }作用域值(Scoped Values): JEP 506 — 正式版
历经 JDK 20-24 五轮迭代后转正, 是
ThreadLocal的现代替代品不可变:
ScopedValue一旦绑定在作用域内不可修改, 消除ThreadLocal的随意set()问题有界生命周期: 绑定的值随
ScopedValue.where(...).run(...)的作用域自动释放虚拟线程友好: 子线程自动继承父线程的 ScopedValue, 且共享存储无需拷贝
// 声明 static final ScopedValue<User> CURRENT_USER = ScopedValue.newInstance(); // 框架层绑定 ScopedValue.where(CURRENT_USER, authenticatedUser).run(() -> { // 在此 lambda 及其调用链中, CURRENT_USER 绑定为 authenticatedUser handleRequest(request, response); }); // 业务层读取 (任意深度调用栈) void handleRequest(...) { User user = CURRENT_USER.get(); // 无需传参 ... }
预览中
主要 API 变化
正式转正
密钥派生函数 API(Key Derivation Function API): JEP 510 — 正式版
标准化 KDF(Key Derivation Functions)的 Java API, 初始支持 HKDF 算法
用于从主密钥派生出不同用途的子密钥
引入(预览)
加密对象的 PEM 编码(PEM Encodings of Cryptographic Objects): JEP 470 — 预览
提供标准 API 用于解析和生成 PEM 格式的密钥、证书等加密对象
告别手动 Base64 + 文件头/尾拼接
稳定值(Stable Values): JEP 502 — 预览
提供
StableValue<T>容器, 用于延迟初始化且只写一次的字段/集合元素与
final字段的 JVM 优化语义等价, 比volatile+ DCL 双重检查锁更安全易用
// 延迟初始化单例, JVM 可像 final 字段一样优化 private final StableValue<Connection> connection = StableValue.of(); Connection getConnection() { return connection.orElseSet(() -> createConnection()); }
主要 JVM 变化
性能提升
AOT 方法剖析(Ahead-of-Time Method Profiling): JEP 515
在 AOT 训练阶段记录方法执行的剖析数据(类型反馈、分支预测等)
后续运行时 JIT 编译器可立即利用历史剖析数据做激进优化, 大幅缩短 "warmup" 时间
AOT 命令行人体工程学(Ahead-of-Time Command-Line Ergonomics): JEP 514
简化 AOT 缓存的使用, 支持通过环境变量或配置文件自动传入 AOT 参数, 无需手动拼长命令行
紧凑对象头(Compact Object Headers): JEP 519 — 产品特性
JDK 24 中的实验性特性升级为正式产品特性
去掉
-XX:+UnlockExperimentalVMOptions限制, 直接通过-XX:+UseCompactObjectHeaders启用Amazon 已在数百个生产服务(包括 JDK 21/17 的反向移植版本)上大规模验证
分代 Shenandoah GC(Generational Shenandoah): JEP 521 — 正式版
从实验性升级为正式特性, 分代 Shenandoah 具备更低的停顿时间和更好的吞吐量
可观测性增强
JFR CPU 时间剖析(JFR CPU-Time Profiling): JEP 509 — 实验性
新增基于 CPU 时间(而非挂钟时间)的 JFR 采样模式, 更精确识别 CPU 密集型热点
JFR 协作式采样(JFR Cooperative Sampling): JEP 518
JFR 在安全点之外也能采样, 提升采样精度, 消除安全点偏差问题
JFR 方法计时与追踪(JFR Method Timing & Tracing): JEP 520
提供 JFR 原生的方法级计时和调用追踪能力, 无需 AOP 框架或字节码插桩
移除
移除 32 位 x86 端口: JEP 503
彻底删除 32 位 x86 平台支持(JDK 24 已废弃
-XX:+UseCompressedOops下的相关代码)
特性演进总览
✅ = 正式转正 🔄 = 行为变更 ❌ = 撤回/移除
升级Java版本的潜在问题与挑战
个人觉得现代 Java 的使用越来越偏底层, 越来越难, 很多黑科技的出现, 比如指令优化等, 大部分是高阶技能, 所以了解这些高级特性是提升个人竞争力的有效途径.
随着Java从8升级到更新的版本, 我们见证了性能、内存管理以及底层支持等多方面的显著提升. 例如, 字符串压缩、ZGC(Z Garbage Collector)和GraalVM等新特性的引入, 极大地增强了Java平台的能力. 然而, 这种进化并非没有代价, 在决定是否进行版本升级时, 开发者必须仔细考虑以下几项关键因素:
废弃的API和包: 一些旧版API如
sun.misc.BASE64Encoder已经被删除, 而像javax这样的包也经历了迁移或弃用. 这意味着依赖这些组件的应用程序可能需要重构以适应新的标准.内部API限制: 对某些内部API(如
Unsafe)的访问权限变得更加严格, 这可能影响那些直接使用这些API实现特定功能的应用程序.垃圾回收机制的变化: 垃圾回收策略的更新可能会改变应用程序的运行行为, 特别是对于那些高度依赖于特定GC行为的应用而言.
第三方库的兼容性: 随着Java版本的迭代, 第三方库也会相应地更新. 虽然它们会添加新特性, 但同时也会停止支持旧的功能或配置. 例如, Spring Boot 3.0之后不再使用
spring.factories文件来加载自动配置类, 如果使用的Spring Boot Starter还未适配新版, 则可能导致应用无法正常启动.注解和工具类的变动: 如
@PostConstruct等注解的处理方式发生变化, 或者新的StackTrace API的引入, 都可能要求第三方框架做出相应的调整, 否则将导致不兼容的问题.项目复杂度的影响: 对于依赖较少的小型项目来说, 升级到更高版本的Java相对简单. 但对于大型项目, 尤其是那些包含多个公共模块的系统, 升级过程可能会非常复杂. 不仅因为内部API的变化, 还因为外部依赖关系的调整需求.
生态系统的演进: 以Spring为例, 其庞大的生态系统使得全面兼容所有JDK版本变得几乎不可能. 因此, 最新的Spring版本已经明确表示不再支持Java 8, 转而拥抱更先进的Java版本, 以减轻历史包袱并推动技术进步.
为了顺利过渡到更新的Java版本, 开发团队应当提前规划, 并确保充分理解上述各项挑战. 此外, 建议对现有代码库进行全面评估, 识别出可能受到版本变更影响的部分, 并制定详细的迁移策略. 对于新的项目开发, 可以充分利用最新Java版本带来的性能优化和其他改进, 但同时也应该意识到随之而来的额外工作量和技术要求.
版本升级兼容常用技巧
添加被移除的包
比较经典就是 javax.xxx 这个包, 有些三方库底层还是用了 javax 的类, 在 JDK 8 可以运行, 升级到 9 以上时就不能用了, 因为这个 javax 已经被移除, 这时候手动引入 javax 依赖, 比如:
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.6.2</version>
</dependency>代码层面逻辑判断兼容
如果使用了将来被移除或者重命名的类, 比如 BASE64Encoder 在 JDK 9 被移除, 为了兼容功能完整性, 需要判断当前运行的 JDK 版本从而在高版本运行环境中切换到其他实现.
String version = System.getProperty("java.version");
if (version.startsWith("1.8")) {
// 使用 BASE64Encoder
} else {
// 高版本实现
}打包时通过 Profile 区别不同版本
如果一个公共类库比如 common-util 中引用了 util-a:1.0, common-util 需要在 JDK 8 及以上版本运行, 而 util-a:1.0 只能在 JDK 8 下运行, 只有 util-a:2.0 才支持更高的版本, 但是 util-a:2.0 需要 JDK 11+ 的编译环形, 所以 common-util 不能在 JDK 8 的环境中升级 util-a 到 2.0 版本.
这个 Case 有两个解决方案:
方案1: 在高版本的项目中引入
common-util, 然后手动排除util-a:1.0并引入 2.0 版本.优点: 简单
缺点: 一般一个
common-util不可能只使用了一个三方库, 也不可能只被一两个项目引用, 所以采用此方案需要每个引用到common-util的项目都手动操作一边, 而且对于未来新增的类库管理不方便.
方案2: 通过 Maven Profile 打包两个版本, 一个给 JDK 8用, 另外一个给更高版本使用. 下面是一个例子, 通过
mvn -Pjdk8 clean install命令打包出一个classifier为jdk8的版本.
<profiles>
<profile>
<id>default</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<JAVA_VERSION>21</JAVA_VERSION>
<JAVA_HOME>~/.jdks/azul-21.0.1</JAVA_HOME>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.5.12</version>
</dependency>
</dependencies>
</profile>
<profile>
<id>jdk8</id>
<properties>
<JAVA_VERSION>1.8</JAVA_VERSION>
<JAVA_HOME>~/.jdks/azul-1.8.0_432</JAVA_HOME>
</properties>
<build>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classifier>jdk8</classifier>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.3.14</version>
</dependency>
</dependencies>
</profile>
</profiles>其他
Java 模块化问题
遇到类似如下问题:
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to unnamed module需要加上启动参数打开包权限(其他包的报错类似):
--add-opens java.base/java.lang=ALL-UNNAMEDmaven-compiler-plugin 以及 maven-surefire-plugin 插件也可能会遇到此问题, 解决方法也是加参数:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<showWarnings>true</showWarnings>
<fork>true</fork>
<compilerArgs>
<!-- 根据报错添加对应的包 -->
<arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED</arg>
</compilerArgs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<includes>
<include>**/*Test.java</include>
</includes>
<argLine>
<!-- 根据情况添加对应的包 -->
--add-opens java.base/java.lang=ALL-UNNAMED
</argLine>
</configuration>
</plugin>Spring Boot
Spring Boot 3.0 Migration Guide
Ref
- 3
- 0
-
赞助
微信
-
分享