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

JDK 13 于 2019 年 9 月 17 日正式发布。

新版本主要包含五个特性

  • 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(动态 CDS 归档)

首先介绍一下 CDS,CDS 全名为 Class Data Sharing,目的是减少Java编程语言应用程序的启动时间,特别是较小的应用程序,并减少内存占用。实现思路是通过JVM调用期间,将共享的归档文件被映射到内存中,从而节省了加载这些类的成本,并允许多个 JVM 进程共享这些类的大部分 JVM 元数据。

JVM 中 CDS 的历史

  • JDK 1.5 引入了CDS 的概念,通过把 rt.jar 中的核心类提前转化成内部表示,转储到一个共享存档(shared archive)中。每个 JVM 只需要装载自己的应用类,启动时间减少了,另外核心类是共享的,所以 JVM 的内存占用也减少了;
  • Oracle JDK 9 中,在支持其他 GC 算法和应用程序类的情况下,这变得非常有用;
  • JDK 10 之前,它一直是一个商业特性,在JDK 10 中它成为了开源的;
  • OpenJDK 13 / JDK 13 中实现了动态 CDS 归档,提高应用程序类数据共享(AppCDS)的可用性。消除了用户为每个应用程序创建类列表而进行试运行的需要。当程序存在时,可以使用 -XX:ArchiveClassesAtExit=<filename>,而不是提供类列表。然后使用 -XX:SharedArchiveFile=<filename>,可以在 JDK 的系统默认存档之上共享类数据

ZGC: Uncommit Unused Memory

ZGC 是在 JDK 11 中引入的,但是到目前为止它还没有像 G1 垃圾收集器那样将未使用的堆内存返回到操作系统。这个 JEP 解决了这个问题,并且默认启用了这个功能。

Reimplement the Legacy Socket API

java.net.Socket 和 java.net.ServerSocket 的实现非常古老,这个 JEP 为它们引入了新的实现。新的实现方法是 Java 13 中的默认实现,但是旧的实现还没有被删除,可以通过设置系统属性 jdk.net.usePlainSocketImpl 来使用它们。但没有为 java.net.DatagramSocket 引入新的实现。

运行一个实例化 Socket 和 ServerSocket 的类将显示这个调试输出。这是默认的(新的实现):

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 是新的实现。

现在让我们设置系统属性并再次运行:

$ 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

它显示了现在使用的旧的实现 java.net.PlainSocketImpl。

Switch Expressions (Preview)

在 JDK 12 中引入了 Switch 表达式作为预览特性。JEP 354 修改了这个特性,它引入了 yield 语句来从块中返回值,而不是使用 break。这意味着,switch 表达式(返回值)应该使用 yield,而 switch 语句(不返回值)应该使用 break。

JDK 13 之前的 Switch 的写法:

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

JDK 13 的 Switch 的写法:

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 特性,但在发布之前就放弃了。JEP 在引入多行字符串文字(一个文本块)方面与此类似。

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

总结:

以上,就是 JDK 13 中包含的 5 个新特性,能够改变开发者编码风格的主要有 Text Blocks 和 Switch Expressions 两个新特性,但是这两个特性还处于预览阶段。

而且,JDK 13 并不是 LTS(长期支持)版本,如果你正在使用 Java 8(LTS)或者 Java 11(LTS),暂时可以不必升级到 Java 13。

想了解更多技术文章,请关注我的公众号:TomScript,获得独家整理的学习资源和日常干货推送。

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

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容