Java语言特性系列
本文主要讲述一下Java14的新特性
java -version
openjdk version "14" 2020-03-17
OpenJDK Runtime Environment (build 14+36-1461)
OpenJDK 64-Bit Server VM (build 14+36-1461, mixed mode, sharing)
从version信息可以看出是build 14+36
JDK14引入了preview版本的针对instanceof的模式匹配,其用法示例如下
public boolean isBadRequestError(Exception ex) {
return (ex instanceof HttpClientErrorException rce) &&
HttpStatus.BAD_REQUEST == rce.getStatusCode();
}
无需在自己进行类型强转
JDK14引入了jdk.incubator.jpackage.jmod,它基于JavaFX javapackager tool构建,目的在于创建一个简单的打包工具,可以用于构建exe、pkg、dmg、deb、rpm格式的安装文件;非模块化的app的构建示例如下
jpackage --name myapp --input lib --main-jar main.jar
实现了NUMA-aware的内存分配,以提升G1在大型机器上的性能
JDK11引入了JFR,使用的时候先dump到磁盘上然后再分析;而在JDK14则支持stream方式来进行持续性的监控,示例如下
public class AgentMain implements Runnable {
public static void premain(String agentArgs, Instrumentation inst) {
try {
Logger.getLogger("AgentMain").log(
Level.INFO, "Attaching JFR Monitor");
new Thread(new AgentMain()).start();
} catch (Throwable t) {
Logger.getLogger("AgentMain").log(
Level.SEVERE,"Unable to attach JFR Monitor", t);
}
}
@Override
public void run() {
var sender = new JfrStreamEventSender();
try (var rs = new RecordingStream()) {
rs.enable("jdk.CPULoad")
.withPeriod(Duration.ofSeconds(1));
rs.enable("jdk.JavaMonitorEnter")
.withThreshold(Duration.ofMillis(10));
rs.onEvent("jdk.CPULoad", sender);
rs.onEvent("jdk.JavaMonitorEnter", sender);
rs.start();
}
}
}
该特性新增了java.base/jdk/internal/misc/ExtendedMapMode.java以支持MappedByteBuffer访问non-volatile memory (NVM)
该特性可以更好地提示哪个地方出现的空指针,需要通过-XX:+ShowCodeDetailsInExceptionMessages开启,示例如下
public class NullPointerExample {
public record City(String name){
}
public record Location(City city) {
}
public record User(String name, Location location) {
}
public static void main(String[] args){
User user = new User("hello", new Location(null));
System.out.println(user.location().city().name());
}
}
输出如下
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "com.example.NullPointerExample$City.name()" because the return value of "com.example.NullPointerExample$Location.city()" is null
at com.example.NullPointerExample.main(NullPointerExample.java:25)
JDK14引入了preview版本的record类型,示例如下
public record Point(int x, int y) {
public Point {
System.out.println(String.format("(%d,%d)", x, y));
}
public Point(int value) {
this(value, value);
}
public static Point of(int value) {
return new Point(value, value);
}
}
javap反编译如下
javac --enable-preview -source 14 Point.java
javap -verbose Point.class
Compiled from "Point.java"
public final class com.example.domain.Point extends java.lang.Record {
public com.example.domain.Point(int, int);
public static com.example.domain.Point of(int);
public java.lang.String toString();
public final int hashCode();
public final boolean equals(java.lang.Object);
public int x();
public int y();
}
可以看见Point继承了java.lang.Record,而且通过invokedynamic提供了final的hashCode及equals
JDK12引入的switch在JDK14变为正式版本,正式版主要是用
->
来替代以前的:
+break
;另外就是提供了yield来在block中返回值,示例如下
public void testSwitchWithArrowBlockAndYield() {
int n = 3;
String quantityString = switch (n) {
case 1 -> "one";
case 2 -> "two";
default -> {
System.out.println("default");
yield "many";
}
};
System.out.println(quantityString);
}
废弃了 Solaris/SPARC, Solaris/x64, and Linux/SPARC ports,以在未来的版本中移除
移除了CMS垃圾收集器,如果在JDK14中使用-XX:+UseConcMarkSweepGC的话,会出现warning,但是不会exit而是以默认的垃圾收集器运行,如下
OpenJDK 64-Bit Server VM warning: Ignoring option UseConcMarkSweepGC; support was removed in 14.0
之前的ZGC只能在linux上使用,现在mac上也能使用ZGC了,示例如下
-XX:+UnlockExperimentalVMOptions -XX:+UseZGC
之前的ZGC只能在linux上使用,现在windows(
不能低于1803版本
)上也能使用ZGC了,示例如下
-XX:+UnlockExperimentalVMOptions -XX:+UseZGC
废弃了parallel young generation GC与SerialOld GC的组合(
-XX:+UseParallelGC与-XX:-UseParallelOldGC配合开启
),现在使用-XX:+UseParallelGC -XX:-UseParallelOldGC或者-XX:-UseParallelOldGC都会出现告警如下
OpenJDK 64-Bit Server VM warning: Option UseParallelOldGC was deprecated in version 14.0 and will likely be removed in a future release.
单独使用-XX:+UseParallelGC则开启parallel young and old generation GC algorithms
移除了Pack200 API
JDK13引入的text blocks进行第二轮preview,JDK14的版本主要增加了两个escape sequences,分别是
\<line-terminator>
与\s escape sequence
,示例如下
@Test
public void testTextBlockWithTwoNewEscapeSequences() {
String inOneLine = """
Lorem ipsum dolor sit amet, consectetur adipiscing \
elit, sed do eiusmod tempor incididunt ut labore \
et dolore magna aliqua.\
""";
System.out.println(inOneLine);
String singleSpace = """
red \s
green\s
blue \s
""";
System.out.println(singleSpace);
}
提供了incubator版本的API用于操纵堆外内存,使用示例如下
@Test
public void testForeignMemoryAccessAPI() {
SequenceLayout intArrayLayout
= MemoryLayout.ofSequence(25,
MemoryLayout.ofValueBits(32,
ByteOrder.nativeOrder()));
VarHandle intElemHandle
= intArrayLayout.varHandle(int.class,
MemoryLayout.PathElement.sequenceElement());
try (MemorySegment segment = MemorySegment.allocateNative(intArrayLayout)) {
MemoryAddress base = segment.baseAddress();
for (int i = 0; i < intArrayLayout.elementCount().getAsLong(); i++) {
intElemHandle.set(base, (long) i, i);
}
}
}
上面列出的是大方面的特性,除此之外还有一些api的更新及废弃,主要见JDK 14 Release Notes,这里举几个例子。
给SAX ContentHandler新增了方法,如下
default void declaration(String version, String encoding, String standalone)
throws SAXException
{
//no op
}
移除了sun.nio.cs.map属性
移除了java.security.acl
移除了默认的keytool -keyalg
废弃了Thread的如下方法
Thread.suspend()
Thread.resume()
ThreadGroup.suspend()
ThreadGroup.resume()
ThreadGroup.allowThreadSuspension(boolean)
已知在macOS上的Dark Mode有Text Visibility Issues
Thread.countStackFrames开启转为无条件地抛出UnsupportedOperationException
Java14主要有如下几个特性