1. 程式人生 > 其它 >JDK 13新特性介紹

JDK 13新特性介紹

JDK 13新特性介紹

1.1 JDK 各版本主要特性回顧

JDK Version 1.0

1996-01-23 Oak(橡樹)

  • 初代版本,偉大的一個里程碑,但是是純解釋執行,使用外掛JIT,效能比較差,執行速度慢。

JDK Version 1.1

1997-02-19

  • JDBC(Java DataBase Connectivity);
  • 支援內部類;
  • RMI(Remote Method Invocation) ;
  • 反射;
  • Java Bean;

JDK Version 1.2

  • 集合框架;
  • JIT(Just In Time)編譯器;
  • 對打包的Java檔案進行數字簽名;
  • JFC(Java Foundation Classes), 包括Swing 1.0, 拖放和Java2D類庫;
  • Java外掛;
  • JDBC中引入可滾動結果集,BLOB,CLOB,批量更新和使用者自定義型別;
  • Applet中新增聲音支援.
  • 同時,Sun釋出了 JSP/Servlet、EJB規範,以及將Java分成了 J2EE、J2SE和J2ME。 這表明了 Java開始向企業、桌面
  • 應用和移動裝置應用3大領域挺進。

JDK Version 1.3

2000-05-08 Kestrel(紅隼)

  • Java Sound API;
  • jar檔案索引;
  • 對Java的各個方面都做了大量優化和增強;

JDK Version 1.4

2004-02-06 Merlin(隼)

  • XML處理;
  • Java列印服務;
  • Logging API;
  • Java Web Start;
  • JDBC 3.0 API;
  • 斷言;
  • Preferences API;
  • 鏈式異常處理;
  • 支援IPV6;
  • 支援正則表示式;
  • 引入Imgae I/O API.

JAVA 5

2004-09-30 Tiger(老虎)

  • 泛型;
  • 增強迴圈,可以使用迭代方式;
  • 自動裝箱與自動拆箱;
  • 型別安全的列舉;
  • 可變引數;
  • 靜態引入;
  • 元資料(註解);
  • Instrumentation;

JAVA 6

2006-12-11 Mustang(野馬)

  • 支援指令碼語言;
  • JDBC 4.0API;
  • Java Compiler API;
  • 可插拔註解;
  • 增加對Native PKI(Public Key Infrastructure), Java GSS(Generic Security Service),Kerberos和LDAP(Lightweight Directory Access Protocol)支援;
  • 繼承Web Services;

JAVA 7

2011-07-28 Dolphin(海豚)

  • switch語句塊中允許以字串作為分支條件;
  • 在建立泛型物件時應用型別推斷;
  • 在一個語句塊中捕獲多種異常;
  • 支援動態語言;
  • 支援try-with-resources(在一個語句塊中捕獲多種異常);
  • 引入Java NIO.2開發包;
  • 數值型別可以用二進位制字串表示,並且可以在字串表示中新增下劃線;
    鑽石型語法(在建立泛型物件時應用型別推斷);
  • null值得自動處理;

JAVA 8

2014-03-18

  • Lambda 表示式 − Lambda允許把函式作為一個方法的引數(函式作為引數傳遞進方法中。
  • 方法引用 − 方法引用提供了非常有用的語法,可以直接引用已有Java類或物件(例項)的方法或構造器。與lambda聯合使用,方法引用可以使語言的構造更緊湊簡潔,減少冗餘程式碼。
  • 預設方法 − 預設方法就是一個在接口裡面有了一個實現的方法。
  • 新工具 − 新的編譯工具,如:Nashorn引擎 jjs、 類依賴分析器jdeps。
  • Stream API −新新增的Stream API(java.util.stream) 把真正的函數語言程式設計風格引入到Java中。
  • Date Time API − 加強對日期與時間的處理。
  • Optional 類 − Optional 類已經成為 Java 8 類庫的一部分,用來解決空指標異常。
  • Nashorn, JavaScript 引擎 − Java 8提供了一個新的Nashorn javascript引擎,它允許我們在JVM上執行特定的javascript應用。

JAVA 9

2017-09-22

  • 模組系統:模組是一個包的容器,Java 9 最大的變化之一是引入了模組系統(Jigsaw 專案)。
    REPL (JShell):互動式程式設計環境。
  • HTTP 2 客戶端:HTTP/2標準是HTTP協議的最新版本,新的 HTTPClient API 支援 WebSocket 和 HTTP2 流以及伺服器推送特性。
  • 改進的 Javadoc:Javadoc 現在支援在 API 文件中的進行搜尋。另外,Javadoc 的輸出現在符合相容 HTML5 標準。
  • 多版本相容 JAR 包:多版本相容 JAR 功能能讓你建立僅在特定版本的 Java 環境中執行庫程式時選擇使用的 class 版本。
  • 集合工廠方法:List,Set 和 Map 介面中,新的靜態工廠方法可以建立這些集合的不可變例項。
  • 私有介面方法:在介面中使用private私有方法。我們可以使用 private 訪問修飾符在介面中編寫私有方法。
  • 程序 API: 改進的 API 來控制和管理作業系統程序。引進 java.lang.ProcessHandle 及其巢狀介面 Info 來讓開發者逃離時常因為要獲取一個本地程序的 PID 而不得不使用原生代碼的窘境。
  • 改進的 Stream API:改進的 Stream API 添加了一些便利的方法,使流處理更容易,並使用收集器編寫複雜的查詢。
  • 改進 try-with-resources:如果你已經有一個資源是 final 或等效於 final 變數,您可以在 try-with-resources 語句中使用該變數,而無需在 try-with-resources 語句中宣告一個新變數。
  • 改進的棄用註解 @Deprecated:註解 @Deprecated 可以標記 Java API 狀態,可以表示被標記的 API 將會被移除,或者已經破壞。
  • 改進鑽石操作符(Diamond Operator) :匿名類可以使用鑽石操作符(Diamond Operator)。
    改進 Optional 類:java.util.Optional 添加了很多新的有用方法,Optional 可以直接轉為 stream。
  • 多解析度影象 API:定義多解析度影象API,開發者可以很容易的操作和展示不同解析度的影象了。
    改進的 CompletableFuture API : CompletableFuture 類的非同步機制可以在 ProcessHandle.onExit 方法退出時執行操作。
  • 輕量級的 JSON API:內建了一個輕量級的JSON API
  • 響應式流(Reactive Streams) API: Java 9中引入了新的響應式流 API 來支援 Java 9 中的響應式程式設計。

JAVA 10

2018-03-21

根據官網的公開資料,共有12個重要特性,如下:

  • JEP286,var 區域性變數型別推斷。
  • JEP296,將原來用 Mercurial 管理的眾多 JDK 倉庫程式碼,合併到一個倉庫中,簡化開發和管理過程
  • JEP304,統一的垃圾回收介面。
  • JEP307,G1 垃圾回收器的並行完整垃圾回收,實現並行性來改善最壞情況下的延遲。
  • JEP310,應用程式類資料 (AppCDS) 共享,通過跨程序共享通用類元資料來減少記憶體佔用空間,和減少啟動時間。
  • JEP312,ThreadLocal 握手互動。在不進入到全域性 JVM 安全點 (Safepoint) 的情況下,對執行緒執行回撥。優化可以只停止單個執行緒,而不是停全部執行緒或一個都不停。
  • JEP313,移除 JDK 中附帶的 javah 工具。可以使用 javac -h 代替。
  • JEP314,使用附加的 Unicode 語言標記擴充套件。
  • JEP317,能將堆記憶體佔用分配給使用者指定的備用記憶體裝置。
  • JEP317,使用 Graal 基於 Java 的編譯器,可以預先把 Java 程式碼編譯成原生代碼來提升效能。
  • JEP318,在 OpenJDK 中提供一組預設的根證書頒發機構證書。開源目前 Oracle 提供的的 Java SE 的根證書,這樣 OpenJDK 對開發人員使用起來更方便。
  • JEP322,基於時間定義的釋出版本,即上述提到的釋出週期。版本號為$FEATURE.$INTERIM.$UPDATE.$PATCH,分j別是大版本,中間版本,升級包和補丁版本。

JAVA 11

2018-09-25

翻譯後的新特性有:

  • 181:Nest-Based訪問控制
  • 309:動態類檔案常量
  • 315:改善Aarch64 intrinsic
  • 318:無操作垃圾收集器
  • 320:消除Java EE和CORBA模組
  • 321:HTTP客戶端(標準)
  • 323:區域性變數的語法λ引數
  • 324:Curve25519和Curve448關鍵協議
  • 327:Unicode 10
  • 328:飛行記錄器
  • 329:ChaCha20和Poly1305加密演算法
  • 330:發射一列縱隊原始碼程式
  • 331:低開銷堆分析
  • 332:傳輸層安全性(Transport Layer Security,TLS)1.3
  • 333:動作:一個可伸縮的低延遲垃圾收集器 (實驗)
  • 335:反對Nashorn JavaScript引擎
  • 336:反對Pack200工具和API

JAVA 12

2018-09-25

翻譯後的新特性有:

  • 189: Shenandoah: A Low-Pause-Time Garbage Collector (Experimental) :新增一個名為 Shenandoah 的垃圾回收器,它通過在 Java 執行緒執行的同時進行疏散 (evacuation) 工作來減少停頓時間。
  • 230: Microbenchmark Suite:新增一套微基準測試,使開發者能夠基於現有的 Java Microbenchmark Harness(JMH)輕鬆測試 JDK 的效能,並建立新的基準測試。
  • 325: Switch Expressions (Preview) :對 switch 語句進行擴充套件,使其可以用作語句或表示式,簡化日常程式碼。
  • 334: JVM Constants API :引入一個 API 來對關鍵類檔案 (key class-file) 和執行時工件的名義描述(nominal descriptions)進行建模,特別是那些可從常量池載入的常量。
  • 340: One AArch64 Port, Not Two :刪除與 arm64 埠相關的所有原始碼,保留 32 位 ARM 移植和 64 位 aarch64 移植。
  • 341: Default CDS Archives :預設生成類資料共享(CDS)存檔。
  • 344: Abortable Mixed Collections for G1 :當 G1 垃圾回收器的回收超過暫停目標,則能中止垃圾回收過程.
  • 346: Promptly Return Unused Committed Memory from G1 :改進 G1 垃圾回收器,以便在空閒時自動將 Java 堆記憶體返回給作業系統。

1.2 JDK 各版本支援週期

為了更快地迭代,Java的更新從傳統的以特性驅動的釋出週期,轉變為以時間驅動的(6 個月為週期)釋出模式
每半年釋出一個大版本,每個季度釋出一箇中間特性版本,並且承諾不會食言。通過這樣的方式,開發團隊可以把
些關鍵特性儘早合併到 JDK 之中,以快速得到開發者反饋,按照官方的說法,新的釋出週期會嚴格遵循時間點,將於每年的3月份和9月份釋出。所以 Java 11 的版本號是18.9(LTS,long term support)。Oracle 直到2023年9月都會為 Java 11 提供技術支援,而補丁和安全警告等擴充套件支援將持續到2026年。新的長期支援版本每三年釋出一次,根據後續的釋出計劃,下一個長期支援版 Java 17 將於2021年釋出

1.3 目前企業JDK版本使用現狀

​ 在 JDK 版本的世界裡,從來都是 Oracle 發他的新版本,我們繼續用我們的老版本。三年之前用 JDK 7,後來終於升級到了 JDK 8。自從升級了沒多久,JDK 就開始了半年發一個新版本的節奏,陸續釋出了 9 、10、11、12,直到(2019年9月17日)釋出了 JDK13。

​ 開發人員在生產中為其應用程式使用了哪些產品?我們可以看到Oracle JDK和OpenJDK在其他所有人的主導地位。2018年12月,由 Snyk 和 The Java Magazine 聯合推出釋出的 2018 JVM 生態調查報告 顯示有 70% 的使用者使用 Oracle JDK,21% 的使用者使用 OpenJDK。

Java 9中的JDK進行了重大的結構更改,許多人預測這將影響遷移和採用。從結果中我們可以看到(請注意,調查是在Java 10和Java 11發行之間進行的),Java 8仍然是Java的最主要版本-十分之八的受訪者表示,他們的主要應用程式在生產中使用了Java 8。同樣重要的是,使用更新版本的非Java 8受訪者不到一半。2018 JVM 生態調查報告](https://snyk.io/blog/jvm-ecosystem-report-2018),[其中 Java 8 的使用者佔到了 79%。

1.4 JDK 13詳細概述

​ 2019年9月17日,國際知名的OpenJDK開源社群釋出了Java程式語言環境的最新版本OpenJDK 13,此次更新是繼半年前 Java 12 這大版本釋出之後的一次常規版本更新,在這一版中,主要帶來了 ZGC 增強、更新 Socket 實現、Switch 表示式,文字塊更新等方面的改動、增強。

1.5 JDK 13 新特性更新列表介紹

網站:http://openjdk.java.net/projects/jdk/13/

1.6 啟動IDEA建立模組整合JDK 13

JDK 13新特性詳解

2.1 JEP 354 switch表示式(預覽)

引入

擴充套件switch分支選擇語句的寫法。Switch表示式在經過JDK 12的預覽之後,在JDK 13中可以繼續使用。

設計初衷

Java的switch語句是一個變化較大的語法(可能是因為Java的switch語句一直不夠強大、熟悉swift或者js語言的同學可與swift的switch語句對比一下,就會發現Java的switch相對較弱),因為Java的很多版本都在不斷地改進switch語句:JDK 12擴充套件了switch語句,使其可以用作語句或者表示式,並且傳統的和擴充套件的簡化版switch都可以使用。

JDK 12對於switch的增強主要在於簡化書寫形式,提升功能點。
下面簡單回顧一下switch的進化階段:

  • 從Java 5+開始,Java的switch語句可使用枚舉了。
  • 從Java 7+開始,Java的switch語句支援使用String型別的變數和表示式了。
  • 從Java 11+開始,Java的switch語句會自動對省略break導致的貫穿提示警告。
  • 但從JDK12開始,Java的switch語句有了很大程度的增強。
  • JDK 13的該JEP是從JEP 325]演變而來的。

以前的switch程式

程式碼如下:

public class Demo01{
    public static void main(String[] args){
        // 宣告變數score,併為其賦值為'C'
        var score = 'C';
        // 執行switch分支語句
        switch (score) {
            case 'A':
                System.out.println("優秀");
                break;
            case 'B':
                System.out.println("良好");
                break;
            case 'C':
                System.out.println("中");
                break;
            case 'D':
                System.out.println("及格");
                break;
            case 'E':
                System.out.println("不及格");
                break;
            default:
                System.out.println("資料非法!");
        }
    }
}

這是經典的Java 11以前的switch寫法 ,這裡不能忘記寫break,否則switch就會貫穿、導致程式出現錯誤(JDK 11會提示警告)。

JDK 13不需要break了

在JDK 12之前如果switch忘記寫break將導致貫穿,在JDK 12對switch的這一貫穿性做了改進。你只要將case後面的冒號(:)改成箭頭,那麼你即使不寫break也不會貫穿了,因此上面程式可改寫如下形式:

public class Demo02{
    public static void main(String[] args){
        // 宣告變數score,併為其賦值為'C'
        var score = 'C';
        // 執行switch分支語句
        switch (score){
            case 'A' -> System.out.println("優秀");
            case 'B' -> System.out.println("良好");
            case 'C' -> System.out.println("中");
            case 'D' -> System.out.println("及格");
            case 'E' -> System.out.println("不及格");
            default -> System.out.println("成績資料非法!");
        }
    }
}

上面程式碼簡潔很多了。

JDK 13的switch表示式

JDK 12之後的switch甚至可作為表示式了——不再是單獨的語句。例如如下程式。

public class Demo03 {
    public static void main(String[] args) {
		// 宣告變數score,併為其賦值為'C'
        var score = 'C';
		// 執行switch分支語句
        String s = switch (score)
                {
                    case 'A' -> "優秀";
                    case 'B' -> "良好";
                    case 'C' -> "中";
                    case 'D' -> "及格";
                    case 'F' -> "不及格";
                    default -> "成績輸入錯誤";
                };
        System.out.println(s);
    }
}

上面程式直接將switch表示式的值賦值給s變數,這樣switch不再是一個語句,而是一個表示式.

JDK 13中switch的多值匹配

當你把switch中的case後的冒號改為箭頭之後,此時switch就不會貫穿了,但在某些情況下,程式本來就希望貫穿比如我就希望兩個case共用一個執行體!JDK 12之後的switch中的case也支援多值匹配,這樣程式就變得更加簡潔了。例如如下程式。

public class Demo04
{
    public static void main(String[] args)
    {
// 宣告變數score,併為其賦值為'C'
        var score = 'B';
// 執行switch分支語句
        String s = switch (score)
                {
                    case 'A', 'B' -> "上等";
                    case 'C' -> "中等";
                    case 'D', 'E' -> "下等";
                    default -> "成績資料輸入非法!";
                };
        System.out.println(s);
    }
}

JDK 13的Yielding a value

當使用箭頭標籤時,箭頭標籤右邊可以是表示式、throw語句或是程式碼塊。如果是程式碼塊,需要使用yield語句來返回值。下面程式碼中的print方法中的default語句的右邊是一個程式碼塊。在程式碼塊中使用yield來返回值。,JDK 13引入了一個新的yield語句來產生一個值,該值成為封閉的switch表示式的值。

public void print(int days) {
  // 宣告變數score,併為其賦值為'C'
  var score = 'B';
  String result = switch (score) {
      case 'A', 'B' -> "上等";
      case 'C' -> "中等";
      case 'D', 'E' -> "下等";
      default -> {
          if (score > 100) {
            yield "資料不能超過100";
          } else {
            yield score + "此分數低於0分";
          }
      }
  };
  System.out.println(result);
}

​ 在switch表示式中不能使用breakswitch表示式的每個標籤都必須產生一個值,或者丟擲異常。switch表示式必須窮盡所有可能的值。這意味著通常需要一個default語句。一個例外是列舉型別。如果窮盡了列舉型別的所有可能值,則不需要使用default。在這種情況下,編譯器會自動生成一個default語句。這是因為列舉型別中的列舉值可能發生變化。比如,列舉型別Color 中原來只有3個值:REDGREENBLUE。使用該列舉型別的switch表示式窮盡了3種情況並完成編譯。之後Color中增加了一個新的值YELLOW,當用這個新的值呼叫之前的程式碼時,由於不能匹配已有的值,編譯器產生的default會被呼叫,告知列舉型別發生改變

小結

從以上案例可以看出JDK 12到JDK 13對switch的功能做了很大的改進,程式碼也十分的簡化,目前來看switch依然是不支援區間匹配的,未來是否可以支援,我們拭目以待。

2.2 JEP 355 文字塊升級(預覽)

引入

在Java中,在字串文字中嵌入HTML,XML,SQL或JSON片段"..."通常需要先進行轉義和串聯的大量編輯,然後才能編譯包含該片段的程式碼。該程式碼段通常難以閱讀且難以維護,因此,如果具有一種語言學機制,可以比多行文字更直觀地表示字串,而且可以跨越多行,而且不會出現轉義的視覺混亂,那麼這將提高廣泛Java類程式的可讀性和可寫性。從JDK 13到JDK 13開始文字塊新特性的提出,提高了Java程式書寫大段字串文字的可讀性和方便性。

HTML示例

使用“一維”字串文字*

String html = "<html>\n" +
              "    <body>\n" +
              "        <p>Hello, world</p>\n" +
              "    </body>\n" +
              "</html>\n";

使用“二維”文字塊

String html = """
              <html>
                  <body>
                      <p>Hello, world</p>
                  </body>
              </html>
              """;
    
System.out.println("""
    Hello,
    itheima
    text blocks!
    """);

文字塊是Java語言的新語法,可以用來表示任何字串,具有更高的表達能力和更少的複雜度。文字塊的開頭定界符是由三個雙引號 """ 開始,從新的一行開始字串的內容。這裡的新起的這行不屬於字串,只表示內容開始,是語法的一部分。以 """ 結束。 """ 可以緊跟字串內容,也可以另起一行。另起一行時,字串內容最後會留有一新行。

"""
line 1
line 2
line 3
"""

等效於字串文字:

"line 1\nline 2\nline 3\n"

或字串文字的串聯:

"line 1\n" +
"line 2\n" +
"line 3\n"

如果在字串的末尾不需要行終止符,則可以將結束定界符放在內容的最後一行。例如,文字塊:

"""
line 1
line 2
line 3"""

等效於字串文字:

"line 1\nline 2\nline 3"

文字塊可以表示空字串,儘管不建議這樣做,因為它需要兩行原始碼:

String empty = """
""";

以下是一些格式錯誤的文字塊的示例:

String a = """""";   // no line terminator after opening delimiter
String b = """ """;  // no line terminator after opening delimiter
String c = """
           ";        // no closing delimiter (text block continues to EOF)
String d = """
           abc \ def
           """;      // unescaped backslash (see below for escape processing)

HTML

使用原始字串語法:

String html = "<html>\n" +
              "    <body>\n" +
              "        <p>Hello, world</p>\n" +
              "    </body>\n" +
              "</html>\n";

使用文字塊文字塊語法:

String html = """
              <html>
                  <body>
                      <p>Hello, world</p>
                  </body>
              </html>
              """;

SQL

使用原始的字串語法:

String query = "SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`\n" +
               "WHERE `CITY` = 'INDIANAPOLIS'\n" +
               "ORDER BY `EMP_ID`, `LAST_NAME`;\n";

使用文字塊語法:

String query = """
               SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`
               WHERE `CITY` = 'INDIANAPOLIS'
               ORDER BY `EMP_ID`, `LAST_NAME`;
               """;

多語言示例

使用原始的字串語法:

ScriptEngine engine = new ScriptEngineManager().getEngineByName("js");
Object obj = engine.eval("function hello() {\n" +
                         "    print('\"Hello, world\"');\n" +
                         "}\n" +
                         "\n" +
                         "hello();\n");

使用文字塊語法:

ScriptEngine engine = new ScriptEngineManager().getEngineByName("js");
Object obj = engine.eval("""
                         function hello() {
                             print('"Hello, world"');
                         }
                         
                         hello();
                         """);

縮排

java編譯器會自動刪除不需要的縮排:

  • 每行結尾的空格都會刪除
  • 每行開始的共有的空格會自動刪除
  • 只保留相對縮排。
System.out.println("""
    Hello,
    itheima
    text blocks!
    """);
// 結果
// > Hello,
// > itheima
// > text blocks!
// >

System.out.println("""
    Hello,
      itheima
    text blocks!
    """);
// 結果
// > Hello,
// >   itheima
// > text blocks!
// >
  • 新行 """ 結束時,將 """ 向左調整,則可以給所有行前加相應數量的空格。將 """ 向右調整,沒有作用。
System.out.println("""
        Hello,
        multiline
        text blocks!
    """);
// 結果
// >     Hello,
// >     multiline
// >     text blocks!

2.3 JEP 350 動態類資料共享歸檔

作用:允許在Java應用程式執行結束時動態歸檔類。歸檔的類將包括預設基層CDS歸檔中不存在的所有已載入應用程式類和庫類。

CDS,是java 12的特性了,可以讓不同 Java 程序之間共享一份類元資料,減少記憶體佔用,它還能加快應用的啟動速度。而JDK13的這個特性支援在Java application執行之後進行動態archive。存檔類將包括預設的基礎層CDS存檔中不存在的所有已載入的應用程式和庫類。也就是說,在Java 13中再使用AppCDS的時候,就不再需要這麼複雜了。該提案處於目標階段,旨在提高AppCDS的可用性,並消除使用者進行試執行以建立每個應用程式的類列表的需要。

目標

JDK13這次對CDS增強的主要目的

  • 改善AppCDS的可用性,減少使用者每次都要建立一個類列表的需要
  • 通過開啟, -Xshare:dump 選項來開啟靜態歸檔,使用類列表仍然行得通。會包含內建的類載入資訊和使用者定義的類載入資訊

意義

在JDK13中做的增強,可以只開啟命令列選項完成上面過程,在程式執行的時候,動態評估那些類需要歸檔,同時支援內建的類載入器和使用者定義的類載入器。

在第一次程式執行完成之後,會自動的將類進行歸檔,後續在啟動專案的時候也無需指定要使用哪些歸檔,整個過程看起來更加的透明。

2.4 JEP 351 ZGC 增強: ZGC 釋放未使用記憶體

目標

作用:將未使用的堆記憶體還給系統(即未提交的記憶體空間)

詳解

ZGC 是 Java 11 中引入的最為矚目的垃圾回收特性,是一種可伸縮、低延遲的垃圾收集器,不過在 Java 11 中是實驗性的引入,主要用來改善 GC 停頓時間,並支援幾百 MB 至幾個 TB 級別大小的堆,並且應用吞吐能力下降不會超過 15%,目前只支援 Linux/x64 位平臺的這樣一種新型垃圾收集器。

通過在實際中的使用,發現 ZGC 收集器中並沒有像 Hotspot 中的 G1 和 Shenandoah 垃圾收集器一樣,能夠主動將未使用的記憶體釋放給作業系統的功能。對於大多數應用程式來說,CPU 和記憶體都屬於有限的緊缺資源,特別是現在使用的雲上或者虛擬化環境中。如果應用程式中的記憶體長期處於空閒狀態,並且還不能釋放給作業系統,這樣會導致其他需要記憶體的應用無法分配到需要的記憶體,而這邊應用分配的記憶體還處於空閒狀態,處於"忙的太忙,閒的太閒"的非公平狀態,並且也容易導致基於虛擬化的環境中,因為這些實際並未使用的資源而多付費的情況。由此可見,將未使用記憶體釋放給系統主記憶體是一項非常有用且亟需的功能。

Java 13 中對 ZGC 的改進,主要體現在下面幾點:

  • 釋放未使用記憶體給作業系統
  • 支援最大堆大小為 16TB

Java 13 中,ZGC 記憶體釋放功能,預設情況下是開啟的,不過可以使用引數:-XX:-ZUncommit 顯式關閉。

2.5 JEP 353 重新實現舊版Socket API

引入

現在已有的 java.net.Socket 和 java.net.ServerSocket 以及它們的實現類,都可以回溯到 JDK 1.0 時代了。原始socket的維護和除錯都很痛苦。實現類還使用了執行緒棧作為 I/O 的緩衝,導致在某些情況下還需要增加執行緒棧的大小。該實現還存在幾個併發問題,需要徹底解決。在未來的網路世界,要快速響應,不能阻塞本地方法執行緒,當前的實現不適合使用了。

詳解

新的實現類

在 Java 13 之前,通過使用 PlainSocketImpl 作為 SocketImpl 的具體實現。

Java 13 中的新底層實現,引入 NioSocketImpl 的實現用以替換 SocketImplPlainSocketImpl 實現,此實現與 NIO(新 I/O)實現共享相同的內部基礎結構,並且與現有的緩衝區快取記憶體機制整合在一起,因此不需要使用執行緒堆疊。除了這些更改之外,還有其他一些更便利的更改,如使用 java.lang.ref.Cleaner 機制來關閉套接字(如果 SocketImpl 實現在尚未關閉的套接字上被進行了垃圾收集),以及在輪詢時套接字處於非阻塞模式時處理超時操作等方面。

全新實現的 NioSocketImpl 來替換JDK1.0的PlainSocketImpl。

  • 它便於維護和除錯,與 NewI/O (NIO) 使用相同的 JDK 內部結構,因此不需要使用系統原生代碼。
  • 它與現有的緩衝區快取機制整合在一起,這樣就不需要為 I/O 使用執行緒棧。
  • 它使用 java.util.concurrent 鎖,而不是 synchronized 同步方法,增強了併發能力。
  • 新的實現是Java 13中的預設實現,但是舊的實現還沒有刪除,可以通過設定系統屬性
    jdk.net.usePlainSocketImpl來切換到舊版本。

程式碼說明

執行一個例項化Socket和ServerSocket的類將顯示這個除錯輸出。這是預設的(新的)。

Module java.base
Package java.net
Class SocketImpl
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")static <S extends SocketImpl & PlatformSocketImpl> S
createPlatformSocketImpl(boolean server) {
    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。

通過這些更改,Java Socket API 將更易於維護,更好地維護將使套接字程式碼的可靠性得到改善。同時 NIO 實現也可以在基礎層面完成,從而保持 Socket 和 ServerSocket 類層面上的不變。

2.6 其他特性

上面列出的是大方面的特性,除此之外還有一些api的更新及廢棄,主要見 JDK 13 Release Notes,這裡舉幾個例
子。
https://jdk.java.net/13/release-notes

增加項

新增FileSystems.newFileSystem(Path, Map<String, ?>) Method
新的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可能造成檔案損壞

展望

Java 在更新發布週期為每半年釋出一次之後,在合併關鍵特性、快速得到開發者反饋等方面,做得越來越好。從 Java 11 到 Java 13,目前確實是嚴格保持半年更新的節奏。Java 13 版本的釋出帶來了些新特性和功能增強、效能提升和改進嘗試。

以上包含的5個特性,能夠改變開發者的編碼風格的主要有Text Blocks和Switch Expressions兩個新特性,但是這兩個特性還處於預覽階段。

而且,JDK13並不是LTS(長期支援)版本,如果你正在使用Java 8(LTS)或者Java 11(LTS),暫時可以不必升級到Java 13。