
自 JDK 8 到 17 以来所有 Java 和 JVM 功能的分类列表
从 Java 8 以来,一直到 16 版本,已有 180 个 JDK Enhancement Proposals (opens new window)(JEPs)塑造 Java,每个 JEP 都给这个平台带来了改善。这篇文章分类梳理了最重要的改进。
目录:
JEPs 的完全列表可以在 OpenJDK 网站下的 jdk (opens new window)和 jdk9 (opens new window)项目找到。
所有的特性基本上都是可用的,且默认开启,除了那些有标记为以下:
- 预览🔍 特性是完全明确且实现的,但还未被认为是最终版本。它们几乎完成,就等实际使用中再来一轮反馈。必须被显示声明开启 (opens new window)。
- 实验💥特性相对没那么稳定,更有可能会有改变。也是需要显示声明开启。
- 孵化🥚 模块不是最终的工具或 API ,会被指定到单独的模块 (opens new window)。
#新语言特性
由于 Java 8 给这个语言带来了许多深具影响的改进,这个章节会简要涵盖下最近几年的更新。想要更深入的了解,参看 New language features since Java 8 to 16 (opens new window)。[1]
记录类,定义不可变 DTO 的精简语法
JDK 16
(opens new window)(JDK 15
(opens new window)JDK 14
(opens new window)为预览特性🔍 )record Point(int x, int y) { } var point = new Point(1, 2); point.x(); // 返回 1 point.y(); // 返回 2
1
2
3
4
5instanceof 模式匹配用于消除类型检查后的显示转化
JDK 16
(opens new window)(JDK 15
(opens new window)JDK 14
(opens new window)为预览特性🔍 )if (obj instanceof String s && s.length() > 5) { System.out.println("obj is a String with more than 5 characters: " + s.toUpperCase()); }
1
2
3封闭类可以限制哪些类能继承
(
JDK 16
(opens new window)JDK 15
(opens new window)为预览特性🔍 )public abstract sealed class Shape permits Circle, Rectangle {...} public class Circle extends Shape {...} // OK public class Rectangle extends Shape {...} // OK public class Triangle extends Shape {...} // 编译错误 // 不再需要 default 分支,已覆盖所有可能的类型 double area = switch (shape) { case Circle c -> Math.pow(c.radius(), 2) * Math.PI case Rectangle r -> r.a() * r.b() };
1
2
3
4
5
6
7
8
9
10
11
12文本块
JDK 15
(opens new window)(JDK 14
(opens new window)JDK 13
(opens new window)为预览特性🔍 )String html = """ <html> <body> <p>Hello, world</p> </body> </html> """;
1
2
3
4
5
6
7有用信息空指针异常
JDK 15
(opens new window)(JDK 14
(opens new window)中需要-XX:+ShowCodeDetailsInExceptionMessages
开启 )a.b.c.i = 99; --- Exception in thread "main" java.lang.NullPointerException: Cannot read field "c" because "a.b" is null
1
2
3
4Switch 表达式
JDK 14
(opens new window)(JDK 13
(opens new window)JDK 12
(opens new window)为预览特性🔍 )int numLetters = switch (day) { case MONDAY, FRIDAY, SUNDAY -> 6; case TUESDAY -> 7; default -> { String s = day.toString(); int result = s.length(); yield result; } };
1
2
3
4
5
6
7
8
9var
关键字引入使得本地变量声明没那么繁琐JDK 11
(opens new window)(JDK 10
(opens new window)中没有 lambda 支持 )var greeting = "Hello World!";
1可选且向后兼容的模块系统,可避免运行时出现
ClassDefNotFoundErrors
和创建内部 APIJDK 9
(opens new window)(Project Jigsaw)module hu.advancedweb.helloworld { requires hu.advancedweb.somedependency; exports hu.advancedweb.hello }
1
2
3
4接口中允许私有方法
JDK 9
(opens new window)(Milling Project Coin)匿名内部类的钻石操作符
JDK 9
(opens new window)(Milling Project Coin)Try-with-resources 语块允许 effectively final 变量
JDK 9
(opens new window)(Milling Project Coin)私有实例方法的
@SafeVargs
注解JDK 9
(opens new window)(Milling Project Coin)import
声明语句不再有废弃警告
#新 API
#通用
Stream.toList
添加为更方便的集合常用方法(取代以前的.collect(Collectors.toList())
)List<String> result = Stream.of("one", "two", "three").stream() .filter(s -> s.length() == 3) .toList();
1
2
3
4Stream.mapMulti
替换(零个或多个元素的)流中的每个元素,flatMap
的一种备选方案Stream.of(1, 2, 3, 4) .mapMulti((number, downstream) -> downstream.accept(number)) .forEach(System.out::print); // 输出 1234
1
2
3相关链接[2]:Faster flatMaps with Stream::mapMulti in Java 16(opens new window)
可指定 HTTP 客户端中筛选请求头的新构造器
DateTimeFormatterBuilder.html#appendDayPeriodText
支持除 AM/PM 外的其它时间区段格式Unix 域 socket channel 和 server-socket channel
矢量 API ,用于描述编译为最佳硬件指令的计算(孵化模块 🥚)
用于静态类型的纯 Java 访问本地代码的外部链接器API (孵化模块 🥚)
用于访问 Java 堆外内存的 API (孵化模块 🥚)
FileChannel API 中支持映射非 volatile (内存)的字节缓冲器
Files.mismatch
: 找出两个文件中第一个不匹配的字节Collectors.teeing
: 用于创建一个由两个下游收集器复合而成的收集器字符串增强:
indent
和transform
方法具有 HTTP/2,WebSocket 支持以及非阻塞 API 特性的标准 HTTP 客户端
JDK 11
(opens new window)(在 JDK 9 (opens new window)中是孵化模块 🥚)HttpClient httpClient = HttpClient.newBuilder().build(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://advancedweb.hu/")) .GET() .build(); HttpResponse<String> response = httpClient.send(request, BodyHandlers.ofString());
1
2
3
4
5
6
7
8
9
10字符串增强,如
isBlank
,lines
,repeat
和strip
方法一些便捷的工厂方法,用于缓解没有集合字面量的不便
Set<Integer> mySet = Set.of(1, 2, 3); List<Integer> myList = List.of(1, 2, 3); Map<String, Integer> myMap = Map.of("one", 1, "two", 2);
1
2
3响应式流的发布/订阅框架,用于非阻塞背压的异步流处理
CompletableFuture
针对时间方面的增强(超时、延迟)更多改变流(
dropWhile
,takeWhile
)和生成流(iterate
,ofNullable
)的选项;只读的收集器(toUnmodifiableList
); Optional 可以转化为流Arrays.mismatch
:找到两个数组中第一个不匹配的元素Stack-Walking API 支持懒访问和栈帧过滤
进程 API 提供更多的信息和控制(例如进程 ID,参数,CPU 时间,父/子进程),加强了
ProcessBuilder
来帮助进程管道的创建varHandle
API 取代java.util.concurrent.atomic
和sun.misc.Unsafe
成员变量和数组相关操作,来提供低层级的访问机制,比如原子写MethodHandle
的新组合体和查找方法改进废弃机制。
@Deprecated
注解中能添加forRemoval
标记,会产生新的警告。OASIS 标准的 XML Catalog API,以安全和高性能的方式管理 XML 中的外部资源
升级 JDK 的 XML 解析器,Xerces,到 2.11.0 版本
Image I/O 框架支持 TIFF 格式
#国际化
Unicode 10.0,新增了大概 27,000 多个字符,10 个区块,以及 30 余种古文字
JDK 11
(opens new window)(JDK 9
(opens new window)中支持 Unicode 8.0)java.util.Locale
和相关 API 支持货币种类,时区等等ResourceBundle
以 UTF-8 编码加载 properties 文件,而不是 ISO-8859-1CLDR 本地化数据默认开启
#图形和桌面应用
面向全平台的桌面特性,比如 login/logout/lock 事件监听器和任务栏交互
MultiResolutionImage
让检索特定分辨率(DPI)图片变得更简单Windows 和 Linux 平台的 HiDPI 图形
Linux 上 JavaFX,Swing 和 AWT 支持 GTK 3
Swing 中 Javadoc 的
@beaninfo
注解替换为@BeanInfo
升级 JavaFX/Media 中 GStreamer 到 1.4.4 版本
HarfBuzz 替换现有的 ICU OpenType 字体排版引擎
#性能提升
#通用
弹性元空间将未使用的 HotSpot 类元数据内存更及时地返还给操作系统
外部内存访问器 API ,安全有效地使用非堆内存(孵化模块 🥚)
允许在 Java 应用执行结束时对类进行动态归档
默认启用默认类列表的类数据共享存档,以改善开箱即用的启动时间
应用类数据共享,通过在Java进程之间共享类元数据来改善启动时间并减少占用空间
节省空间的紧凑型字符串,更有效地存储只有 Latin-1 字符的字符串
性能分析和未分析的编译代码缓存被分离开,以提高性能和内存占用
将 intern 字符串存储在类数据共享档案中,以减少内存消耗
#库
改进 AArch64 处理器上
java.lang.Math
的sin
、cos
和log
函数的内部函数安全管理器的性能提升
Spin-Wait 提示 (
Thread#onSpinWait
) 来优化繁忙等待式循环替换 Java 2D 中 Pisces 渲染器成 Marlin 作为默认的图形光栅化器
使用最近推出的 SPARC 和英特尔 x64 CPU 指令,以提高 GHASH 和 RSA 性能
#并发
Thread-Local 握手机制以停止个别线程
提高被竞争对象的 monitor 性能
在线程堆栈上为关键部分提供额外空间,减小
java.util.concurrent
的 locks 在堆栈溢出时出现死锁的风险
#编译器
Linux 平台支持 Ahead-of-Time 编译功能(实验特性💥)
JDK 10
(opens new window)(Graal 作为实验性的 JIT 编译器)JDK 9
(opens new window)(JVM 编译器接口)JDK 9
(opens new window)(Graal 作为 AoT 编译器)
#G1 垃圾收集器(默认)
- NUMA( non-uniform memory access )感知的内存分配
JDK 14
(opens new window) - 可中止的混合收集,以满足用户提供的暂停目标
JDK 12
(opens new window) - 空闲时自动将堆内存返回给操作系统
JDK 12
(opens new window) - 并行 Full GC 以改善最坏情况下的延迟
JDK 10
(opens new window) - 将并行 GC 替换为 G1 作为默认垃圾收集器
JDK 9
(opens new window)
#其它垃圾收集器
Z 垃圾收集器,在大的堆空间上提供非常低的暂停时间
JDK 16
(opens new window)JDK 15
(opens new window)(实验特性💥JDK 14
(opens new window)(Windows)JDK 14
(opens new window)(OS X)JDK 11
(opens new window)(Linux) )Shenandoah 垃圾收集器, 提供同 ZGC 类似的好处,但基于不同的算法
JDK 15
(opens new window)(JDK 12
(opens new window)中为实验特性💥)Epsilon 垃圾收集器, 未实现实际的内存回收,力求最低开销
JDK 11
(opens new window)XX:AllocateHeapAt=<path>
支持可替代的存储器设备JDK 10
(opens new window)
#诊断分析及工具
- Flight Recorder 事件流: 可通过 API (opens new window)提供性能分析数据, 使其适用于连续监测
JDK 14
(opens new window) - 基于 JMH 的微基准测试套件[3]
JDK 12
(opens new window) - Flight Recorder 成为 OpenJDK 的一部分
JDK 11
(opens new window) - 通过 JMTI 进行低开销堆性能分析
JDK 11
(opens new window) - C1 和 C2 编译器的运行时可管理和特定方法控制实现包含的测试
JDK 9
(opens new window) - 为 JVM 所有组件提供的细粒度、易配置的日志系统
JDK 9
(opens new window)(Unified JVM Logging) JDK 9 (opens new window)(Unified GC Logging) - 允许应用程序提供日志实现,供平台类使用
JDK 9
(opens new window)
#安全改进
- JDK 提供一组默认的根认证机构 (CA) 证书,TLS 连接可开箱即用
JDK 10
(opens new window) - 验证传入的序列化数据
JDK 9
(opens new window) - 默认的密钥存储类型是标准的 PKCS12,而不是专属的 JKS
JDK 9
(opens new window) - 基于 DRBG (Deterministic Random Bit Generator) 的
SecureRandom
JDK 9
(opens new window) - 禁用基于 SHA-1 签名的 X.509 证书链
JDK 9
(opens new window) - SHA-3 哈希算法
JDK 9
(opens new window)
#TLS
支持 TLS 1.3
JDK 11
(opens new window)数据报传输层安全 ( DTLS, Datagram Transport Layer Security ) 的 API
JDK 9
(opens new window)实现 TLS 的 OCSP 修订 ( Online Certificate Status Protocol (OCSP) stapling ) ,提高证书状态检查的性能
JDK 9
(opens new window)TLS 应用层协议协商 ( ALPN, Application-Layer Protocol Negotiation ) 扩展,无需额外的来回通信即可进行协议协商;ALPN 是 HTTP/2 连接的要求
JDK 9
(opens new window)
#加密
- Edwards-Curve 电子签名算法 (EdDSA) - RFC8032 (opens new window)
JDK 15
(opens new window) - 使用 Curve25519 和 Curve448 的密钥协议
JDK 11
(opens new window) - ChaCha20 和 Poly1305 加密算法
JDK 11
(opens new window)
#启动
- 支持启动单文件源码程序,包括 Unix 的 Shebang (
#!
) 行JDK 11
(opens new window) jshell
: Java 的「读取-求值-输出」循环 ( Read-Eval-Print Loop, REPL ) 编程环境JDK 9
(opens new window)(Project Kulla) 相关链接[2:1]: Prototyping with JShell(opens new window)- 用
--release
编译旧的平台版本,配置--source
和--target
并链接到相应的平台版本JDK 9
(opens new window) - JVM 命令行标记的提前校验,避免崩溃
JDK 9
(opens new window)
#打包
- 用于创建单文件应用 ( self-contained applications ) 的打包工具,也支持原生包格式:msi,exe,pkg,dmg,deb 和 rpm
JDK 16
(opens new window)( 孵化模块 🥚 inJDK 14
(opens new window)) 相关链接[2:2]:Inside Java - Episode 12 “jpackage” with Kevin Rushforth(opens new window) jlink
Java Linker,可为模块化 Java 应用程序构建一个优化的、精简的运行时映像,该映像只包含 JDK 的所需部分JDK 9
(opens new window)- [2 (opens new window)], [3 (opens new window)], [4 (opens new window)], [4 (opens new window)], [5 (opens new window)]- 多版本 JAR 文件允许多个 Java 版本的类在一个打包文件
JDK 9
(opens new window)
#Javadoc
- Javadoc 工具现在使用 HTML5 ,而不是基于 iframe 的布局,文档包含一个搜索框以方便导航
JDK 9
(opens new window)- [2 (opens new window)], [3 (opens new window)]
#字节码
用
Unsafe::defineAnonymousClass()
替换Lookup::defineHiddenClass()
,使框架动态生成隐藏类,这些类不能被其它类发现、链接或直接使用java.lang.invoke.constant
包允许轻松的描述可加载常量(ldc
指令的运算元 ),这比依赖临时的 String 表示法更不易出错JDK 12
(opens new window)CONSTANT_Dynamic
常量池条目,使用引导的方式进行解析,和INVOKEDYNAMIC
调用类似JDK 11
(opens new window)引入 Nest 访问控制上下文,将类包装在同一代码实体中,例如嵌套类,避免了编译器向生成的字节码插入桥接方法的需要
JDK 11
(opens new window)为静态字符串连接生成的字节码使用
invokedynamic
而不是直接创建StringBuilder#append
链。这将使未来的字符串连接优化不需要字节码变动JDK 9
(opens new window)INVOKEDYNAMIC
可以表示对象属性和/或集合的高层级操作JDK 9
(opens new window)
#新支持平台
- Alpine
JDK 16
(opens new window) - Windows/AArch64
JDK 16
(opens new window) - Linux/AArch64
JDK 9
(opens new window) - Linux/s390x
JDK 9
(opens new window) - Unified arm32/arm64
JDK 9
(opens new window)
#新版本号格式
#废弃和移除
默认情况下对内部 API 强封装 (
sun.*
), 除了一些关键 API (opens new window),例如sun.misc.Unsafe
解开强封装由启动器参数--illegal-access
(opens new window)控制JDK 16
(opens new window)(Deprecated inJDK 9
(opens new window)- [2 (opens new window)])废弃原始包装器类的构造函数,不允许在包装器对象上进行同步 (
Byte
,Short
,Integer
,Long
,Float
,Double
,Boolean
, 和Character
)JDK 16
(opens new window)移除 Javascript 引擎 Nashorn 和
jjs
工具JDK 15
(opens new window)(Deprecated inJDK 11
(opens new window))移除 Solaris 和 SPARC 平台移植
JDK 15
(opens new window)(Deprecated inJDK 14
(opens new window))废弃 RMI Activation (opens new window),影响
java.rmi.activation
包和rmid
工具,一般不会影响 Java RMIJDK 15
(opens new window)默认禁用 偏向锁 (opens new window),废弃相关的命令行参数
JDK 15
(opens new window)废弃
Unsafe::defineAnonymousClass()
JDK 15
(opens new window)移除 Concurrent Mark Sweep (CMS) 垃圾收集器
JDK 14
(opens new window)废弃 ParallelScavenge + SerialOld GC 的组合
JDK 14
(opens new window)移除 Pack200 工具及其 API
JDK 14
(opens new window)废弃 Pack200 工具及其 API
JDK 11
(opens new window)移除 Java EE
JDK 11
(opens new window)移除 CORBA
JDK 11
(opens new window)移除
Thread#destroy
和Thread#stop
JDK 11
(opens new window)var
不再是合法的类名JDK 10
(opens new window)移除 javah 工具
JDK 10
(opens new window)下划线不再是合法的变量名
JDK 9
(opens new window)移除
apple.applescript
和com.apple
包JDK 9
(opens new window)禁用基于 SHA-1 签名的 X.509 证书链
JDK 9
(opens new window)移除 Launch-Time JRE 版本选择指令:
JRE-Version
清单条目和-version:
命令行选项JDK 9
(opens new window)移除 jhat 工具
JDK 9
(opens new window)移除 JVM TI hprof 代理
JDK 9
(opens new window)移除 JDK 8 中废弃的 GC 组合
JDK 9
(opens new window)废弃 Applet API
JDK 9
(opens new window)废弃 Concurrent Mark Sweep (CMS) 垃圾收集器
JDK 9
(opens new window)废弃
Object.finalize()
JDK 9
(opens new window)移除 JRE 中的认可标准覆盖 (
lib/endorsed
) 和扩展 (lib/ext
) 机制JDK 9
(opens new window)移除 JRE 中的
rt.jar
JDK 9
(opens new window)如果你对 Java 8 和 14 之间所有 API 级别的差异有兴趣,请查看
Java Almanac
(opens new window)项目。此外,还可以查看Java类依赖分析器jdeps
(opens new window),找出你的项目是否还在使用旧的内部 API。
#总结
JDK 8
(opens new window)是在 2014 年发布的。我们不得不为 JDK 9
(opens new window)等待三年半的时间。 但从那时起,就快了起来。Java 有一个新的发布架构,目标是每六个月提供一个新版本。
虽然现在仍然支持 Java 8,但迁移到最新版本会带来相当多的改进。
译者注:
这篇文章也有翻译:参看 Java 9 到 16 的语言特性更新 (opens new window)↩︎
译者有写相关的介绍文章 (opens new window)↩︎
本文来自:https://nanova.me/java-lang-jvm-updates/