JDK13的六大重要新特性

JDK13的六大重要特性

JDK13在9月17號全球首發了,Oracle JDK 13經過改善Java SE平臺和JDK的性能,穩定性和安全性來提升開發人員的生產力。此次的JDK13包含了5個JEP(Java Enhancement Proposals)和一個Unicode 12.1的支持總共6大主要新特性。下面咱們一一詳細說明。html

  • 支持Unicode 12.1
  • 動態CDS歸檔(Dynamic CDS Archiving)
  • java.net.Socket和java.net.ServerSocket API的從新實現
  • ZGC的加強
  • 文本塊(預覽語言功能)
  • switch表達式(預覽語言功能)

支持Unicode 12.1

java.lang.Character支持12.1級別的Unicode字符數據庫,其中12.0自11.0起增長了554個字符,總共137,928個字符。 這些增長的內容包括4個新腳本,總共150個腳本,以及61個新表情符號字符。 自12.0起,12.1正好加一個字符,即U+32FF (SQUARE ERA NAME REIWA)。java

java.text.Bidi和java.text.Normalizer類分別支持12.0級Unicode標準附件#9和#15。算法

java.util.regex軟件包支持基於Unicode標準附件#29的12.0級的擴展字素集羣數據庫

動態CDS歸檔(Dynamic CDS Archiving)

相對於默認CDS存檔,在HotSpot中使用AppCDS歸檔應用程序類可提供額外的啓動時間和內存優點。可是,當前須要三步過程才能將AppCDS用於Java應用程序:緩存

  1. 進行一次或屢次試運行以建立class列表
  2. 將建立的class列表轉儲存檔
  3. 而後和該存檔一塊兒運行

此外,此過程僅適用於僅使用內置類加載器的應用程序。使用用戶自定義的類加載器的應用程序使用起來並不容易,目前在HotSpot中僅僅是實驗性的支持。安全

經過命令行選項啓用的動態歸檔將經過消除試運行(上面的步驟1)來簡化AppCDS的使用,並將有效,統一地支持內置類加載器和用戶定義的類加載器。服務器

此JEP的後續加強功能能夠在應用程序的第一次運行期間執行自動存檔生成。這將消除顯式的存檔建立步驟(上面的步驟2)。 從而讓CDS / AppCDS的使用變得徹底透明和自動。性能

該動態歸檔支持如下類型:編碼

  • 當成功映射兩個存檔時,支持靜態基本存檔(默認CDS存檔)+動態存檔
  • 當沒法映射動態存檔時,僅靜態基本存檔

當前,動態存檔要求將默認CDS存檔用做基本存檔。若是沒法在運行時映射和使用基本層歸檔,則將自動禁用頂層動態歸檔。spa

怎麼使用?

若是指定了-XX:ArchiveClassesAtExit選項,則當應用程序退出時,將動態建立共享檔案。

動態生成的存檔是在與運行的JDK映像打包在一塊兒的默認系統存檔的頂部建立的。 將爲每一個應用程序生成一個單獨的頂層存檔文件。 用戶能夠將動態檔案名稱的文件名指定爲-XX:ArchiveClassesAtExit選項的參數。 例如,如下命令建立hello.jsa:

%bin / java -XX:ArchiveClassesAtExit = hello.jsa -cp hello.jar Hello

要使用此動態存檔運行同一應用程序: %bin / java -XX:SharedArchiveFile = hello.jsa -cp hello.jar Hello

java.net.Socket和java.net.ServerSocket API的從新實現

java.net.Socket和java.net.ServerSocket API將全部套接字操做委託給java.net.SocketImpl,這是自JDK 1.0起已經存在的服務提供程序接口(SPI)機制。內置的實現稱爲「普通」實現,由非公開的PlainSocketImpl經過支持類SocketInputStream和SocketOutputStream實施。

PlainSocketImpl由其餘兩個JDK內部實現擴展,這些實現支持經過SOCKS和HTTP代理服務器的鏈接。默認狀況下,使用基於SOCKS的SocketImpl建立Socket和ServerSocket(有時是延遲的)。在ServerSocket的狀況下,使用SOCKS實現是一個古怪的事情,能夠追溯到對JDK 1.4中的代理服務器鏈接的實驗性(而且自從刪除以來)支持。

新的實現NioSocketImpl替代了PlainSocketImpl。它被開發爲易於維護和調試。它與新I / O(NIO)實現共享相同的JDK內部基礎結構,所以不須要本身的本機代碼。它與現有的緩衝區高速緩存機制集成在一塊兒,所以不須要將線程堆棧用於I / O。它使用java.util.concurrent鎖而不是同步方法,以便未來能夠在fibers上很好地使用。在JDK 11中,大多數NIO SocketChannel和其餘SelectableChannel實現都是在實現相同目標的狀況下從新實現的。

ZGC的加強

ZGC當前不會uncommit並將內存返回給操做系統,即便該內存已經使用了很長時間也是如此。 對於全部類型的應用程序和環境,尤爲是那些關注內存佔用的應用程序和環境,此行爲都不是最佳的。

HotSpot中的其餘垃圾收集器(例如G1和Shenandoah)現在都提供了此功能,ZGC也將添加這個樣的功能。

ZGC堆由一組稱爲ZPages的堆區域組成。每一個ZPage與可變數量的已提交堆內存關聯。當ZGC壓縮堆時,ZPage被釋放並插入到頁面緩存ZPageCache中。頁面緩存中的ZPage已準備好重用以知足新的堆分配,在這種狀況下,它們將從緩存中刪除。頁面緩存對於性能相當重要,由於提交和取消提交內存是昂貴的操做。

頁面緩存中的ZPages集合表示堆中未使用的部分,這些部分可能還沒有提交併返回給操做系統。所以,能夠經過簡單地從頁面緩存中清除一組精心選擇的ZPage,而後取消提交與這些頁面關聯的內存來取消提交內存。頁面緩存已經使ZPage保持最近使用(LRU)的順序,並按大小(小,中和大)進行了分隔,所以退出ZPage和取消提交內存的機制相對簡單。挑戰在於設計策略,該策略決定什麼時候該從緩存中逐出ZPage。

一個簡單的策略是擁有一個超時或延遲值,該值指定ZPage在退出以前能夠在頁面緩存中停留多長時間。此超時將具備一些合理的默認值,並帶有命令行選項來覆蓋它。 Shenandoah GC使用這樣的策略,默認值爲5分鐘,並使用命令行選項-XX:ShenandoahUncommitDelay = 覆蓋默認策略。

相似於上述政策的一項政策可能會至關有效。可是,也能夠設想更復雜的策略,而不涉及添加新的命令行選項。例如,啓發式算法根據GC頻率或其餘一些數據找到合適的超時值。咱們最初將使用-XX:ZUncommitDelay = 選項提供一個簡單的超時策略,而後再提供一種更復雜的策略(若是找到)。

uncommit功能將默認啓用。可是不管策略決定了什麼,ZGC都不該uncommit內存,以使堆低於其最小大小(-Xms)。這意味着,若是以最小堆大小(-Xms)等於最大堆大小(-Xmx)啓動JVM,則會有效禁用取消提交功能。也將提供選項-XX:-ZUncommit以顯式禁用此功能。

最後,Linux / x64上的ZGC使用tmpfs或hugetlbfs文件來備份堆。Uncommitting這些文件使用的內存須要具備FALLOC_FL_PUNCH_HOLE支持的fallocate(2),該支持最先出如今Linux 3.5(tmpfs)和4.3(hugetlbfs)中。在較舊的Linux內核上運行時,ZGC應該繼續像之前同樣工做,但禁用了uncommit功能。

文本塊(預覽語言功能)

文本塊是一個預覽語言功能,可能會在後面的版本進行修改或者刪除。

文本塊是一種多行字符串文字,它避免了大多數轉義序列的須要,以一種可預測的方式自動設置字符串的格式,並在須要時使開發人員能夠控制格式。 這是JDK 13中的預覽語言功能。

HTML example

傳統方式:

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 example

傳統方式:

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`;
               """;
複製代碼

switch表達式(預覽語言功能)

擴展switch使其能夠用做語句或表達式,從而使兩種形式均可以使用: 傳統的case ...:labels(須要break)或新case ...->labels(不須要break) ,還有另外一個新語句,用於從switch表達式產生值。 這些更改將簡化平常編碼。 這是JDK 13中的預覽語言功能。

原始寫法:

switch (day) {
    case MONDAY:
    case FRIDAY:
    case SUNDAY:
        System.out.println(6);
        break;
    case TUESDAY:
        System.out.println(7);
        break;
    case THURSDAY:
    case SATURDAY:
        System.out.println(8);
        break;
    case WEDNESDAY:
        System.out.println(9);
        break;
}
複製代碼

最新寫法:

switch (day) {
    case MONDAY, FRIDAY, SUNDAY -> System.out.println(6);
    case TUESDAY                -> System.out.println(7);
    case THURSDAY, SATURDAY     -> System.out.println(8);
    case WEDNESDAY              -> System.out.println(9);
}
複製代碼

switch 表達式,用於返回值:

int numLetters = switch (day) {
    case MONDAY, FRIDAY, SUNDAY -> 6;
    case TUESDAY                -> 7;
    case THURSDAY, SATURDAY     -> 8;
    case WEDNESDAY              -> 9;
};
複製代碼

更多教程請參考 flydean的博客

相關文章
相關標籤/搜索