JDK14新特性
- Pattern Matching for instanceof (Preview)
- Non-Volatile Mapped Byte Buffers (Incubator)
- Helpful NullPointerExceptions
- Switch Expressions (Standard)
- Packaging Tool (Incubator)
- NUMA-Aware Memory Allocation for G1
- JFR Event Streaming
- Records (Preview)
- Deprecate the Solaris and SPARC Ports
- Remove the Concurrent Mark Sweep (CMS) Garbage Collector
- ZGC on macOS (experimental)
- ZGC on Windows (experimental)
- Deprecate the ParallelScavenge + SerialOld GC Combination
- Remove the Pack200 Tools and API
- Text Blocks (Second Preview)
- Foreign-Memory Access API (Incubator)
2020年3月17日,Java 14(Java SE 14)及其Java开发工具包14(JDK 14)开源发布。本文主要记录了JDK14的16个新特性。
本文的IDE为IDEA2020.1,JDK14是通过IDE下载的Open JDK.
Pattern Matching for instanceof (Preview)
instanceof的模式匹配(预览版)
String s = "instance";
//before jdk14
if (s instanceof String) {
String str = s;
System.out.println("before jdk14:" + str);
}
//in jdk14
if (s instanceof String str) {
System.out.println("before jdk14:" + str);
}
if (s instanceof String str && str.equals("instance")) {
System.out.println("TRUE");
}
仅当object不为null时,instanceOf才会匹配,然后仅将其分配给str。 在instanceof中使用模式匹配应减少Java程序中显式强制转换的总数。
Non-Volatile Mapped Byte Buffers (Incubator)
新增了java.base/jdk/internal/misc/ExtendedMapMode.java以支持MappedByteBuffer访问non-volatile
memory (NVM)。
从JDK1.4开始,Java引入了NIO文件相关的API,带有MappedByteBuffer的FileChannel将文件数据的一部分加载到虚拟内存中,然后引入了称为Path的新增强功能。 当我们使用Java NIO时,Path是一个接口,它将java.io.File类替换为文件或目录的表示形式。
现在,Java 14对MappedByteBuffer进行了增强,以将部分文件数据加载到非易失性内存(NVM)中。 非易失性存储器或非易失性存储器是计算机存储器,即使关闭电源(例如ROM(只读存储器),闪存,硬盘等存储设备)也不会丢失/删除数据。 如果像RAM一样关闭电源,则无法保留数据。 唯一需要的API更改是FileChannel客户端采用的新枚举,以请求映射位于NVM支持的文件系统而不是传统文件存储系统上的文件。
Helpful NullPointerExceptions
JVM生成的NullPointerExceptions(NPE)异常消息的改进。可以更好地提示哪个地方出现的空指针,需要通过-XX:+ShowCodeDetailsInExceptionMessages开启。 对于程序过早终止,这将对开发人员和支持人员有帮助的信息。 由于NPE几乎可以出现在程序中的任何位置,因此尝试捕获它们并从中恢复通常是不切实际的。
//NullPointerExceptions
pojo p = new pojo(null);
System.out.println(p.getApple().getColor());
在此之前,报错时这样的:
现在在运行参数中配置:-XX:+ShowCodeDetailsInExceptionMessages,开启Helpful NullPointerExceptions:
开启之后,运行结果是这样的:
如图所示,准确的告知了我们哪个变量为null。
Switch Expressions (Standard)
JDK14扩展了switch语句,在JDK12种已引入,在JDK14中变为了正式版。现在的case中使用->来替代以前的:+break,而且提供了yield来在block中返回值;
//switch
//before JDK14
Calendar calendar = Calendar.getInstance();
Integer today = calendar.get(Calendar.DAY_OF_WEEK);
String weekday = "";
switch (today) {
case Calendar.MONDAY:
case Calendar.TUESDAY:
case Calendar.WEDNESDAY:
case Calendar.THURSDAY:
case Calendar.FRIDAY:
weekday = "weekday";
break;
case Calendar.SATURDAY:
case Calendar.SUNDAY:
weekday = "weekend";
break;
default:
throw new IllegalStateException("Unexpected value: " + today);
}
System.out.println("Before JDK14:"+weekday);
//in JDK14
weekday = switch (today) {
case Calendar.MONDAY, Calendar.TUESDAY, Calendar.WEDNESDAY, Calendar.THURSDAY, Calendar.FRIDAY -> "weekday";
case Calendar.SATURDAY, Calendar.SUNDAY -> "weekend";
default -> {
yield "unknown";
//throw new IllegalStateException("Unexpected value: " + Calendar.DAY_OF_WEEK);
}
};
System.out.println("JDK14:"+weekday);
Packaging Tool (Incubator)
打包工具(孵化中)
JDK14引入了jdk.incubator.jpackage.jmod,它基于JavaFX javapackager tool构建,目的在于创建一个简单的打包工具。
jpackage工具将Java应用程序捆绑到特定于平台的程序包中,其中包含所需的所有依赖项。作为一组普通的JAR文件或作为模块的集合。
可以用于构建以下文件格式的安装文件:
- Linux: deb and rpm
- macOS: pkg and dmg
- Windows: msi and exe
非模块化的app的构建示例如下:
jpackage --name myapp --input lib --main-jar main.jar
NUMA-Aware Memory Allocation for G1
NUMA-Aware Memory Allocation(NUMA)是一种将微处理器集群配置为多处理系统的方法,因此可以在本地共享内存,可以提高性能并扩展系统的功能。
Java 14提供了可识别NUMA的内存分配功能,以提高大型计算机上的G1性能。
G1的堆组织为固定大小区域的集合。一个区域通常是一组物理页面,尽管使用大页面(通过-XX:+ UseLargePages)时,多个区域可能组成一个物理页面。
如果指定了+ XX:+ UseNUMA选项,则在初始化JVM时,区域将平均分布在可用NUMA节点的总数上。
JFR Event Streaming
JDK11引入了JFR,使用的时候先dump到磁盘上然后再分析;而在JDK14则支持stream方式来进行进程内和进程外应用程序的持续性监控。
Records (Preview)
JDK14引入了预览版本的record类型。在开发中,我们需要编写许多重复代码,编写简单的实体类:构造函数,getter 和 setter,equals(),hashCode(),toString()等。为避免这种重复代码,Java计划使用Records。
在此前的实体类:
而在JDK14的预览版中,只需一行代码就可以实现等同于以上的效果。
让我们来看看编译后的AppleRecord实体类,它长这样:
可以看到AppleRecord继承了java.lang.Record,而且生成了final的hashCode()及equals()方法,但是却没有了setter方法,getter方法也省略了get前缀。
Deprecate the Solaris and SPARC Ports
废弃Solaris / SPARC,Solaris / x64和Linux / SPARC端口,以便将来删除。
通过取消对这些端口的支持,OpenJDK社区中的贡献者将能够加速新功能的开发,以推动平台向前发展。
构建配置更改
以下内容会导致尝试配置Solaris和/或SPARC:
$ bash ./configure
...
checking compilation type... native
configure: error: The Solaris and SPARC ports are deprecated and may be removed in a future release. \
Use --enable-deprecated-ports=yes to suppress this error.
configure exiting with result code 1
$
新的–enable-deprecated-ports = yes 配置项将消除该错误并继续。
$ bash ./configure --enable-deprecated-ports=yes
...
checking compilation type... native
configure: WARNING: The Solaris and SPARC ports are deprecated and may be removed in a future release.
...
Build performance summary:
* Cores to use: 32
* Memory limit: 96601 MB
为Solaris和SPARC(包括Solaris / SPARC,Solaris / x64,Linux / SPARC)配置构建时,将发出错误/警告。
Remove the Concurrent Mark Sweep (CMS) Garbage Collector
移除了CMS垃圾收集器。此更新将停用CMS编译,从源树中删除gc / cms目录的内容,并删除仅CMS选项。如果在JDK14中使用-XX:+UseConcMarkSweepGC的话,会出现警告,但是不会退出而是以默认的垃圾收集器运行。
ZGC on macOS (experimental)
之前的ZGC只能在linux上使用,现在mac上也能使用了。
ZGC on Windows (experimental)
之前的ZGC只能在linux上使用,现在windows(不能低于1803版本)上也能使用。
Deprecate the ParallelScavenge + SerialOld GC Combination
废弃了parallel young generation GC与SerialOld GC的组合( -XX:+UseParallelGC与-XX:-UseParallelOldGC配合开启),现在使用-XX:+UseParallelGC -XX:-UseParallelOldGC或者-XX:-UseParallelOldGC都会出现告警。
Remove the Pack200 Tools and API
移除了Pack200 API。
Text Blocks (Second Preview)
在Java中,要将HTML,XML,SQL或JSON代码片段嵌入到代码中通常很难阅读且难以保留,并且为了克服此问题,Java 14引入了Text Block。
JDK13引入的text blocks进行第二轮预览,JDK14的版本主要增加了两个escape sequences,分别是 <line-terminator>与\s escape sequence。
由三个英文双引号(""")开始/结束。与字符串文字中的字符不同,内容可以直接包含双引号字符。 允许在文本块中使用\“,但不是必需的或不建议使用。"""可以使字符可以不转义出现,并且还可以从视觉上区分文本块和字符串文字。
//HTML without text block
String html = "<html>\n" +
" <body>\n" +
" <p>Hello, world</p>\n" +
" </body>\n" +
"</html>\n";
//HTML with text block
String htmlTextBlock = """
<html>
<body>
<p>Hello, world</p>
</body>
</html>
""";
Foreign-Memory Access API (Incubator)
提供了孵化版本的API用于操纵堆外内存。