版本號
<code>java -version
openjdk version "13" 2019-12-17
OpenJDK Runtime Environment (build 13+33)
OpenJDK 64-Bit Server VM (build 13+33, mixed mode, sharing)/<code>
從version信息可以看出是build 13+33
特性列表
350: Dynamic CDS Archives
JDK5引入了Class-Data Sharing可以用於多個JVM共享class,提升啟動速度,最早只支持system classes及serial GC
JDK9對其進行擴展以支持application classes及其他GC算法
java10的新特性JEP 310: Application Class-Data Sharing擴展了JDK5引入的Class-Data Sharing,支持application的Class-Data Sharing並開源出來(以前是commercial feature)
JDK11將-Xshare:off改為默認-Xshare:auto,以更加方便使用CDS特性
JDK12的341: Default CDS Archives即在64-bit平臺上編譯jdk的時候就默認在${JAVA_HOME}/lib/server目錄下生成一份名為classes.jsa的默認archive文件(大概有18M)方便大家使用
JDK13的這個特性支持在Java application執行之後進行動態archive
- 導出jsa
<code>java -XX:ArchiveClassesAtExit=hello.jsa -cp hello.jar Hello/<code>
- 使用jsa
<code>java -XX:SharedArchiveFile=hello.jsa -cp hello.jar Hello/<code>
351: ZGC: Uncommit Unused Memory
Java12的346: Promptly Return Unused Committed Memory from G1新增了兩個參數分別是G1PeriodicGCInterval及G1PeriodicGCSystemLoadThreshold用於GC之後重新調整Java heap size,然後將多餘的內存歸還給操作系統
Java12的189: Shenandoah: A Low-Pause-Time Garbage Collector (Experimental)擁有參數-XX:ShenandoahUncommitDelay=<milliseconds>來指定ZPage的page cache的失效時間,然後歸還內存
Java13則給ZGC新增歸還unused heap memory給操作系統的特性;它新增了幾個參數,-XX:ZUncommitDelay=<seconds>用於指定ZPage的page cache的失效時間;ZGC的歸還內存默認是開啟的,可以使用-XX:-ZUncommit來顯式禁用/<seconds>/<milliseconds>
353: Reimplement the Legacy Socket API
本特性替換了java.net.Socket以及java.net.ServerSocket API的底層實現;它使用NioSocketImpl來替換JDK1.0的PlainSocketImpl;如果要繼續使用舊版的Socket實現,可以使用-Djdk.net.usePlainSocketImpl參數來切換到舊版本
/Library/Java/JavaVirtualMachines/jdk-13.jdk/Contents/Home/lib/src.zip!/java.base/java/net/SocketImpl.java
<code>public abstract class SocketImpl implements SocketOptions {
private static final boolean USE_PLAINSOCKETIMPL = usePlainSocketImpl();
private static boolean usePlainSocketImpl() {
PrivilegedAction<string> pa = () -> NetProperties.get("jdk.net.usePlainSocketImpl");
String s = AccessController.doPrivileged(pa);
return (s != null) && !s.equalsIgnoreCase("false");
}
/**
* Creates an instance of platform's SocketImpl
*/
@SuppressWarnings("unchecked")
staticS createPlatformSocketImpl(boolean server) {/<string>/<code>
if (USE_PLAINSOCKETIMPL) {
return (S) new PlainSocketImpl(server);
} else {
return (S) new NioSocketImpl(server);
}
}
//......
}
SocketImpl的USE_PLAINSOCKETIMPL取決於usePlainSocketImpl方法,而它會從NetProperties讀取dk.net.usePlainSocketImpl配置,如果不為null且不為false,則usePlainSocketImpl方法返回true;createPlatformSocketImpl會根據USE_PLAINSOCKETIMPL來創建PlainSocketImpl或者NioSocketImpl
354: Switch Expressions (Preview)
本特性主要是使用yield替換了break來避免歧義,因為break可以用來進行跳轉執行類似goto的操作
<code> @Test
public void testSwitchYield(){
String dayOfWeek = switch(1){
case 1 -> {
String day = "Monday";
yield day;
}
case 2 -> {
String day = "Tuesday";
yield day;
}
default -> "Unknown";
};
System.out.println(dayOfWeek);
}/<code>
355: Text Blocks (Preview)
本特性主要引入了Text Blocks,使用"""來包圍一段text block,可以內置佔位符最後使用String.format來填充
<code> @Test
public void testTextBlock(){
// Without Text Blocks
String html = "\\n" +
" \\n" +
"Hello, Escapes
\\n" +
" \\n" +
"\\n";
System.out.println(html);
// With Text Blocks
String html2 = """
Hello, %s
""";
System.out.println(String.format(html2, "World"));
String htmlWithNewLine = """
Hello World
""";
System.out.print(htmlWithNewLine);
System.out.println("a new line");
}/<code>
需要注意text blocks不能在一行,另外如果結尾的"""在新的一行則會輸出新的一行
細項解讀
上面列出的是大方面的特性,除此之外還有一些api的更新及廢棄,主要見JDK 13 Release Notes,這裡舉幾個例子。
添加項
- 添加FileSystems.newFileSystem(Path, Map<string>) Method/<string>
- 新的java.nio.ByteBuffer Bulk get/put Methods Transfer Bytes Without Regard to Buffer Position
- 支持Unicode 12.1
- 添加-XX:SoftMaxHeapSize Flag,目前僅僅對ZGC起作用
- ZGC的最大heap大小增大到16TB
移除項
- 移除awt.toolkit System Property
- 移除Runtime Trace Methods
- 移除-XX:+AggressiveOpts
- 移除Two Comodo Root CA Certificates、Two DocuSign Root CA Certificates
- 移除內部的com.sun.net.ssl包
廢棄項
- 廢棄-Xverify:none及-noverify
- 廢棄rmic Tool並準備移除
- 廢棄javax.security.cert並準備移除
已知問題
- 不再支持Windows 2019 Core Server
- 使用ZIP File System (zipfs) Provider來更新包含Uncompressed Entries的ZIP或JAR可能造成文件損壞
其他事項
- GraphicsEnvironment.getCenterPoint()及getMaximumWindowBounds()已跨平臺統一
- 增強了JAR Manifest的Class-Path屬性處理
jdk.net.URLClassPath.showIgnoredClassPathEntries屬性設置為true可以用來幫助查看非法的Class-Path entries
- 針對Negatively Sized Argument,StringBuffer(CharSequence)及StringBuilder(CharSequence)會拋出NegativeArraySizeException
- linux的默認進程啟動機制已經使用posix_spawn
- Lookup.unreflectSetter(Field)針對static final fields會拋出IllegalAccessException
- 使用了java.net.Socket.setSocketImplFactory及java.net.ServerSocket.setSocketFactory方法的要注意,要求客戶端及服務端要一致,不能一端使用自定義的factory一端使用默認的factory
- SocketImpl的supportedOptions, getOption及setOption方法的默認實現發生了變化,默認的supportedOptions返回空,而默認的getOption,及setOption方法拋出UnsupportedOperationException
- JNI NewDirectByteBuffer創建的Direct Buffer為java.nio.ByteOrder.BIG_ENDIAN
- Base64.Encoder及Base64.Decoder可能拋出OutOfMemoryError
- 改進了Serial GC Young pause time report
- 改進了MaxRAM及UseCompressedOops參數的行為
小結
- Java13主要新增瞭如下特性350: Dynamic CDS Archives351: ZGC: Uncommit Unused Memory353: Reimplement the Legacy Socket API354: Switch Expressions (Preview)355: Text Blocks (Preview)
- 語法層面,改進了Switch Expressions,新增了Text Blocks,二者皆處於Preview狀態;API層面主要使用NioSocketImpl來替換JDK1.0的PlainSocketImpl
- GC層面則改進了ZGC,以支持Uncommit Unused Memory
版本號
<code>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)/<code>
從version信息可以看出是build 14+36
特性列表
305:Pattern Matching for instanceof (Preview)
JDK14引入了preview版本的針對instanceof的模式匹配,其用法示例如下
<code> public boolean isBadRequestError(Exception ex) {
return (ex instanceof HttpClientErrorException rce) &&
HttpStatus.BAD_REQUEST == rce.getStatusCode();
}/<code>
無需在自己進行類型強轉
343:Packaging Tool (Incubator)
JDK14引入了jdk.incubator.jpackage.jmod,它基於JavaFX javapackager tool構建,目的在於創建一個簡單的打包工具,可以用於構建exe、pkg、dmg、deb、rpm格式的安裝文件;非模塊化的app的構建示例如下
<code>jpackage --name myapp --input lib --main-jar main.jar/<code>
345:NUMA-Aware Memory Allocation for G1
實現了NUMA-aware的內存分配,以提升G1在大型機器上的性能
349:JFR Event Streaming
JDK11引入了JFR,使用的時候先dump到磁盤上然後再分析;而在JDK14則支持stream方式來進行持續性的監控,示例如下
<code>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();
}
}
}/<code>
352:Non-Volatile Mapped Byte Buffers
該特性新增了java.base/jdk/internal/misc/ExtendedMapMode.java以支持MappedByteBuffer訪問non-volatile memory (NVM)
358:Helpful NullPointerExceptions
該特性可以更好地提示哪個地方出現的空指針,需要通過-XX:+ShowCodeDetailsInExceptionMessages開啟,示例如下
<code>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());
}
}/<code>
輸出如下
<code>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)/<code>
359:Records (Preview)
JDK14引入了preview版本的record類型,示例如下
<code>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);
}
}/<code>
javap反編譯如下
<code>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();
}/<code>
可以看見Point繼承了java.lang.Record,而且通過invokedynamic提供了final的hashCode及equals
361:Switch Expressions (Standard)
JDK12引入的switch在JDK14變為正式版本,正式版主要是用->來替代以前的:+break;另外就是提供了yield來在block中返回值,示例如下
<code> 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);
}/<code>
362:Deprecate the Solaris and SPARC Ports
廢棄了 Solaris/SPARC, Solaris/x64, and Linux/SPARC ports,以在未來的版本中移除
363:Remove the Concurrent Mark Sweep (CMS) Garbage Collector
移除了CMS垃圾收集器,如果在JDK14中使用-XX:+UseConcMarkSweepGC的話,會出現warning,但是不會exit而是以默認的垃圾收集器運行,如下
<code>OpenJDK 64-Bit Server VM warning: Ignoring option UseConcMarkSweepGC; support was removed in 14.0/<code>
364:ZGC on macOS
之前的ZGC只能在linux上使用,現在mac上也能使用ZGC了,示例如下
<code>-XX:+UnlockExperimentalVMOptions -XX:+UseZGC/<code>
365:ZGC on Windows
之前的ZGC只能在linux上使用,現在windows(不能低於1803版本)上也能使用ZGC了,示例如下
<code>-XX:+UnlockExperimentalVMOptions -XX:+UseZGC/<code>
366:Deprecate the ParallelScavenge + SerialOld GC Combination
廢棄了parallel young generation GC與SerialOld GC的組合( -XX:+UseParallelGC與-XX:-UseParallelOldGC配合開啟),現在使用-XX:+UseParallelGC -XX:-UseParallelOldGC或者-XX:-UseParallelOldGC都會出現告警如下
<code>OpenJDK 64-Bit Server VM warning: Option UseParallelOldGC was deprecated in version 14.0 and will likely be removed in a future release./<code>
單獨使用-XX:+UseParallelGC則開啟parallel young and old generation GC algorithms
367:Remove the Pack200 Tools and API
移除了Pack200 API
368:Text Blocks (Second Preview)
JDK13引入的text blocks進行第二輪preview,JDK14的版本主要增加了兩個escape sequences,分別是 \\<line-terminator>與\\s escape sequence,示例如下/<line-terminator>
<code> @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);
}/<code>
370:Foreign-Memory Access API (Incubator)
提供了incubator版本的API用於操縱堆外內存,使用示例如下
<code> @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);
}
}
}/<code>
細項解讀
上面列出的是大方面的特性,除此之外還有一些api的更新及廢棄,主要見JDK 14 Release Notes,這裡舉幾個例子。
添加項
- New Method to SAX ContentHandler for Handling XML Declaration (JDK-8230814)
給SAX ContentHandler新增了方法,如下
<code> default void declaration(String version, String encoding, String standalone)
throws SAXException
{
//no op
}/<code>
移除項
- Removal of sun.nio.cs.map System Property (JDK-8229960)
移除了sun.nio.cs.map屬性
- Removed Deprecated java.security.acl APIs (JDK-8191138)
移除了java.security.acl
- Removal of the Default keytool -keyalg Value (JDK-8214024)
移除了默認的keytool -keyalg
廢棄項
- Thread Suspend/Resume Are Deprecated for Removal (JDK-8231602)
廢棄了Thread的如下方法
<code>Thread.suspend()
Thread.resume()
ThreadGroup.suspend()
ThreadGroup.resume()
ThreadGroup.allowThreadSuspension(boolean)/<code>
已知問題
- Text Visibility Issues in macOS Dark Mode (JDK-8228555)
已知在macOS上的Dark Mode有Text Visibility Issues
其他事項
- Thread.countStackFrames Changed to Unconditionally Throw UnsupportedOperationException (JDK-8205132)
Thread.countStackFrames開啟轉為無條件地拋出UnsupportedOperationException
小結
Java14主要有如下幾個特性
- 305:Pattern Matching for instanceof (Preview)
- 349:JFR Event Streaming
- 352:Non-Volatile Mapped Byte Buffers
- 358:Helpful NullPointerExceptions
- 359:Records (Preview)
- 361:Switch Expressions (Standard)
- 363:Remove the Concurrent Mark Sweep (CMS) Garbage Collector
- 364:ZGC on macOS
- 366:Deprecate the ParallelScavenge + SerialOld GC Combination
- 368:Text Blocks (Second Preview)
- 370:Foreign-Memory Access API (Incubator)
閱讀更多 青峰科技 的文章