Java語言特性系列
本文主要講述一下Java14的新特性html
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,這裏舉幾個例子。java
給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主要有以下幾個特性linux