Java 13 最新特性你知道多少?

JDK 13 于 2019 年 9 月 17 日正式發(fā)布。

新版本主要包含五個(gè)特性

  • JEP 350: Dynamic CDS Archives
  • JEP 351: ZGC: Uncommit Unused Memory
  • JEP 353: Reimplement the Legacy Socket API
  • JEP 354: Switch Expressions (Preview)
  • JEP 355: Text Blocks (Preview)

Dynamic CDS Archives(動(dòng)態(tài) CDS 歸檔)

首先介紹一下 CDS,CDS 全名為 Class Data Sharing,目的是減少Java編程語(yǔ)言應(yīng)用程序的啟動(dòng)時(shí)間,特別是較小的應(yīng)用程序,并減少內(nèi)存占用。實(shí)現(xiàn)思路是通過(guò)JVM調(diào)用期間,將共享的歸檔文件被映射到內(nèi)存中,從而節(jié)省了加載這些類(lèi)的成本,并允許多個(gè) JVM 進(jìn)程共享這些類(lèi)的大部分 JVM 元數(shù)據(jù)。

JVM 中 CDS 的歷史

  • JDK 1.5 引入了CDS 的概念,通過(guò)把 rt.jar 中的核心類(lèi)提前轉(zhuǎn)化成內(nèi)部表示,轉(zhuǎn)儲(chǔ)到一個(gè)共享存檔(shared archive)中。每個(gè) JVM 只需要裝載自己的應(yīng)用類(lèi),啟動(dòng)時(shí)間減少了,另外核心類(lèi)是共享的,所以 JVM 的內(nèi)存占用也減少了;
  • Oracle JDK 9 中,在支持其他 GC 算法和應(yīng)用程序類(lèi)的情況下,這變得非常有用;
  • JDK 10 之前,它一直是一個(gè)商業(yè)特性,在JDK 10 中它成為了開(kāi)源的;
  • OpenJDK 13 / JDK 13 中實(shí)現(xiàn)了動(dòng)態(tài) CDS 歸檔,提高應(yīng)用程序類(lèi)數(shù)據(jù)共享(AppCDS)的可用性。消除了用戶為每個(gè)應(yīng)用程序創(chuàng)建類(lèi)列表而進(jìn)行試運(yùn)行的需要。當(dāng)程序存在時(shí),可以使用 -XX:ArchiveClassesAtExit=<filename>,而不是提供類(lèi)列表。然后使用 -XX:SharedArchiveFile=<filename>,可以在 JDK 的系統(tǒng)默認(rèn)存檔之上共享類(lèi)數(shù)據(jù)

ZGC: Uncommit Unused Memory

ZGC 是在 JDK 11 中引入的,但是到目前為止它還沒(méi)有像 G1 垃圾收集器那樣將未使用的堆內(nèi)存返回到操作系統(tǒng)。這個(gè) JEP 解決了這個(gè)問(wèn)題,并且默認(rèn)啟用了這個(gè)功能。

Reimplement the Legacy Socket API

java.net.Socketjava.net.ServerSocket 的實(shí)現(xiàn)非常古老,這個(gè) JEP 為它們引入了新的實(shí)現(xiàn)。新的實(shí)現(xiàn)方法是 Java 13 中的默認(rèn)實(shí)現(xiàn),但是舊的實(shí)現(xiàn)還沒(méi)有被刪除,可以通過(guò)設(shè)置系統(tǒng)屬性 jdk.net.usePlainSocketImpl 來(lái)使用它們。但沒(méi)有為 java.net.DatagramSocket 引入新的實(shí)現(xiàn)。

運(yùn)行一個(gè)實(shí)例化 SocketServerSocket 的類(lèi)將顯示這個(gè)調(diào)試輸出。這是默認(rèn)的(新的實(shí)現(xiàn)):

java -XX:+TraceClassLoading JEP353  | grep Socket
[0.033s][info   ][class,load] java.net.Socket source: jrt:/java.base
[0.035s][info   ][class,load] java.net.SocketOptions source: jrt:/java.base
[0.035s][info   ][class,load] java.net.SocketImpl source: jrt:/java.base
[0.039s][info   ][class,load] java.net.SocketImpl$$Lambda$1/0x0000000800b50840 source: java.net.SocketImpl
[0.042s][info   ][class,load] sun.net.PlatformSocketImpl source: jrt:/java.base
[0.042s][info   ][class,load] sun.nio.ch.NioSocketImpl source: jrt:/java.base
[0.043s][info   ][class,load] sun.nio.ch.SocketDispatcher source: jrt:/java.base
[0.044s][info   ][class,load] java.net.DelegatingSocketImpl source: jrt:/java.base
[0.044s][info   ][class,load] java.net.SocksSocketImpl source: jrt:/java.base
[0.044s][info   ][class,load] java.net.ServerSocket source: jrt:/java.base
[0.045s][info   ][class,load] jdk.internal.access.JavaNetSocketAccess source: jrt:/java.base
[0.045s][info   ][class,load] java.net.ServerSocket$1 source: jrt:/java.base

sun.nio.ch 上面的 NioSocketImpl 是新的實(shí)現(xiàn)。

現(xiàn)在讓我們?cè)O(shè)置系統(tǒng)屬性并再次運(yùn)行:

$ java -Djdk.net.usePlainSocketImpl -XX:+TraceClassLoading JEP353  | grep Socket
[0.037s][info   ][class,load] java.net.Socket source: jrt:/java.base
[0.039s][info   ][class,load] java.net.SocketOptions source: jrt:/java.base
[0.039s][info   ][class,load] java.net.SocketImpl source: jrt:/java.base
[0.043s][info   ][class,load] java.net.SocketImpl$$Lambda$1/0x0000000800b50840 source: java.net.SocketImpl
[0.046s][info   ][class,load] sun.net.PlatformSocketImpl source: jrt:/java.base
[0.047s][info   ][class,load] java.net.AbstractPlainSocketImpl source: jrt:/java.base
[0.047s][info   ][class,load] java.net.PlainSocketImpl source: jrt:/java.base
[0.047s][info   ][class,load] java.net.AbstractPlainSocketImpl$1 source: jrt:/java.base
[0.047s][info   ][class,load] sun.net.ext.ExtendedSocketOptions source: jrt:/java.base
[0.047s][info   ][class,load] jdk.net.ExtendedSocketOptions source: jrt:/jdk.net
[0.047s][info   ][class,load] java.net.SocketOption source: jrt:/java.base
[0.047s][info   ][class,load] jdk.net.ExtendedSocketOptions$ExtSocketOption source: jrt:/jdk.net
[0.047s][info   ][class,load] jdk.net.SocketFlow source: jrt:/jdk.net
[0.047s][info   ][class,load] jdk.net.ExtendedSocketOptions$PlatformSocketOptions source: jrt:/jdk.net
[0.047s][info   ][class,load] jdk.net.ExtendedSocketOptions$PlatformSocketOptions$1 source: jrt:/jdk.net
[0.048s][info   ][class,load] jdk.net.LinuxSocketOptions source: jrt:/jdk.net
[0.048s][info   ][class,load] jdk.net.LinuxSocketOptions$$Lambda$2/0x0000000800b51040 source: jdk.net.LinuxSocketOptions
[0.049s][info   ][class,load] jdk.net.ExtendedSocketOptions$1 source: jrt:/jdk.net
[0.049s][info   ][class,load] java.net.StandardSocketOptions source: jrt:/java.base
[0.049s][info   ][class,load] java.net.StandardSocketOptions$StdSocketOption source: jrt:/java.base
[0.051s][info   ][class,load] sun.net.ext.ExtendedSocketOptions$$Lambda$3/0x0000000800b51440 source: sun.net.ext.ExtendedSocketOptions
[0.057s][info   ][class,load] java.net.DelegatingSocketImpl source: jrt:/java.base
[0.057s][info   ][class,load] java.net.SocksSocketImpl source: jrt:/java.base
[0.058s][info   ][class,load] java.net.ServerSocket source: jrt:/java.base
[0.058s][info   ][class,load] jdk.internal.access.JavaNetSocketAccess source: jrt:/java.base
[0.058s][info   ][class,load] java.net.ServerSocket$1 source: jrt:/java.base

它顯示了現(xiàn)在使用的舊的實(shí)現(xiàn) java.net.PlainSocketImpl

Switch Expressions (Preview)

在 JDK 12 中引入了 Switch 表達(dá)式作為預(yù)覽特性。JEP 354 修改了這個(gè)特性,它引入了 yield 語(yǔ)句來(lái)從塊中返回值,而不是使用 break。這意味著,switch 表達(dá)式(返回值)應(yīng)該使用 yield,而 switch 語(yǔ)句(不返回值)應(yīng)該使用 break。

JDK 13 之前的 Switch 的寫(xiě)法:

int i;
switch (x) {
    case "1":
        i = 1;
        break;
    case "2":
        i = 2;
        break;
    default:
        i = x.length();
        break;
}

JDK 13 的 Switch 的寫(xiě)法:

switch (x) {
    case "1" -> 1;
    case "2" -> 2;
    default -> {
        int len = x.length();
        yield len;
    }
}

或者

switch (x) {
    case "1": yield 1;
    case "2": yield 2;
    default: {
        int len = x.length();
        yield len;
    }
}

Text Blocks (Preview)

JDK 12 中引入了 Raw String Literals 特性,但在發(fā)布之前就放棄了。JEP 在引入多行字符串文字(一個(gè)文本塊)方面與此類(lèi)似。

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`;
               """;

總結(jié):

以上,就是 JDK 13 中包含的 5 個(gè)新特性,能夠改變開(kāi)發(fā)者編碼風(fēng)格的主要有 Text BlocksSwitch Expressions 兩個(gè)新特性,但是這兩個(gè)特性還處于預(yù)覽階段。

而且,JDK 13 并不是 LTS(長(zhǎng)期支持)版本,如果你正在使用 Java 8(LTS)或者 Java 11(LTS),暫時(shí)可以不必升級(jí)到 Java 13。

想了解更多技術(shù)文章,請(qǐng)關(guān)注我的公眾號(hào):TomScript,獲得獨(dú)家整理的學(xué)習(xí)資源和日常干貨推送。

原文鏈接:https://blog.sagowiec.com/article/4

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容