New Features in Java 13 – Java 13的新功能

最后修改: 2020年 1月 20日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

September 2019 saw the release of JDK 13, per Java’s new release cadence of six months. In this article, we’ll take a look at the new features and improvements introduced in this version.

2019年9月,按照Java新的六个月的发布节奏,JDK 13发布了。在这篇文章中,我们将看一下这个版本中引入的新功能和改进。

2. Preview Developer Features

2.预览开发者功能

Java 13 has brought in two new language features, albeit in the preview mode. This implies that these features are fully implemented for developers to evaluate, yet are not production-ready. Also, they can either be removed or made permanent in future releases based on feedback.

Java 13带来了两个新的语言功能,尽管是在预览模式下。这意味着这些功能已经完全实现,可供开发人员评估,但还不具备生产条件。此外,根据反馈意见,它们可以被删除或在未来的版本中成为永久性的。

We need to specify –enable-preview as a command-line flag to use the preview features. Let’s look at them in-depth.

我们需要指定-enable-preview作为一个命令行标志来使用预览功能。让我们深入了解一下它们。

2.1. Switch Expressions (JEP 354)

2.1.切换表达式(JEP 354)

We initially saw switch expressions in JDK 12. Java 13’s switch expressions build on the previous version by adding a new yield statement.

我们最初是在JDK 12中看到开关表达式的。Java 13的switch表达式在前一个版本的基础上增加了一个新的yield语句。

Using yield, we can now effectively return values from a switch expression:

使用yield,我们现在可以有效地从开关表达式中返回值

@Test
@SuppressWarnings("preview")
public void whenSwitchingOnOperationSquareMe_thenWillReturnSquare() {
    var me = 4;
    var operation = "squareMe";
    var result = switch (operation) {
        case "doubleMe" -> {
            yield me * 2;
        }
        case "squareMe" -> {
            yield me * me;
        }
        default -> me;
    };

    assertEquals(16, result);
}

As we can see, it’s now easy to implement the strategy pattern using the new switch.

正如我们所看到的,现在很容易使用新的switch.实现strategy模式

2.2. Text Blocks (JEP 355)

2.2. 文本块(JEP 355

The second preview feature is text blocks for multi-line Strings such as embedded JSON, XML, HTML, etc.

第二个预览功能是文本块,用于多行字符串,如嵌入式JSON、XML、HTML等。

Earlier, to embed JSON in our code, we would declare it as a String literal:

早些时候,为了在我们的代码中嵌入JSON,我们会把它声明为一个String 字段。

String JSON_STRING 
  = "{\r\n" + "\"name\" : \"Baeldung\",\r\n" + "\"website\" : \"https://www.%s.com/\"\r\n" + "}";

Now let’s write the same JSON using String text blocks:

现在让我们用String 文本块来写同样的JSON。

String TEXT_BLOCK_JSON = """
{
    "name" : "Baeldung",
    "website" : "https://www.%s.com/"
}
""";

As is evident, there is no need to escape double quotes or to add a carriage return. By using text blocks, the embedded JSON is much simpler to write and easier to read and maintain.

显而易见,不需要转义双引号,也不需要添加回车键。通过使用文本块,嵌入式JSON的编写更加简单,更容易阅读和维护。

Moreover, all String functions are available:

此外,所有的String函数都可以使用。

@Test
public void whenTextBlocks_thenStringOperationsWorkSame() {        
    assertThat(TEXT_BLOCK_JSON.contains("Baeldung")).isTrue();
    assertThat(TEXT_BLOCK_JSON.indexOf("www")).isGreaterThan(0);
    assertThat(TEXT_BLOCK_JSON.length()).isGreaterThan(0);
}

Also, java.lang.String now has three new methods to manipulate text blocks:

另外,java.lang.String现在有三个新方法来操作文本块。

  • stripIndent() – mimics the compiler to remove incidental white space
  • translateEscapes() – translates escape sequences such as “\\t” to “\t”
  • formatted() – works the same as String::format, but for text blocks

Let’s take a quick look at a String::formatted example:

让我们快速看一下String::formatted的例子。

assertThat(TEXT_BLOCK_JSON.formatted("baeldung").contains("www.baeldung.com")).isTrue();
assertThat(String.format(JSON_STRING,"baeldung").contains("www.baeldung.com")).isTrue();

Since text blocks are a preview feature and can be removed in a future release, these new methods are marked for deprecation.

由于文本块是一个预览功能,可以在未来的版本中删除,这些新方法被标记为废弃。

3. Dynamic CDS Archives (JEP 350)

3.动态CDS档案(JEP 350)

Class data sharing (CDS) has been a prominent feature of Java HotSpot VM for a while now. It allows class metadata to be shared across different JVMs to reduce startup time and memory footprint. JDK 10 extended this ability by adding application CDS (AppCDS) – to give developers the power to include application classes in the shared archive. JDK 12 further enhanced this feature to include CDS archives by default.

一段时间以来,类数据共享(CDS)一直是Java HotSpot VM的一个突出功能。它允许在不同的JVM之间共享类元数据,以减少启动时间和内存占用。JDK 10 通过添加应用程序 CDS(AppCDS)扩展了这一能力 – 让开发人员有能力在共享存档中包含应用程序类。JDK 12 进一步增强了这一功能,默认包括CDS 存档

However, the process of archiving application classes was tedious. To generate archive files, developers had to do trial runs of their applications to create a class list first, and then dump it into an archive. After that, this archive could be used to share metadata between JVMs.

然而,归档应用程序类的过程是很繁琐的。为了生成归档文件,开发人员必须先试运行他们的应用程序以创建一个类列表,然后将其转储到一个归档文件中。之后,这个归档文件可以被用来在JVM之间共享元数据。

With dynamic archiving, JDK 13 has simplified this process. Now we can generate a shared archive at the time the application is exiting. This has eliminated the need for trial runs.

通过动态归档,JDK 13简化了这个过程。现在我们可以在应用程序退出时生成共享存档。这就消除了试运行的需要。

To enable applications to create a dynamic shared archive on top of the default system archive, we need to add an option -XX:ArchiveClassesAtExit and specify the archive name as argument:

为了使应用程序能够在默认的系统存档之上创建一个动态的共享存档,我们需要添加一个选项-XX:ArchiveClassesAtExit并指定存档名称作为参数。

java -XX:ArchiveClassesAtExit=<archive filename> -cp <app jar> AppName

We can then use the newly created archive to run the same app with -XX:SharedArchiveFile option:

然后我们可以使用新创建的归档文件,用-XX:SharedArchiveFile选项运行同一个应用程序。

java -XX:SharedArchiveFile=<archive filename> -cp <app jar> AppName

4. ZGC: Uncommit Unused Memory (JEP 351)

4.ZGC:取消提交未使用的内存(JEP 351)

The Z Garbage Collector was introduced in Java 11 as a low-latency garbage collection mechanism, such that GC pause times never exceeded 10 ms. However, unlike other HotSpot VM GCs such as G1 and Shenandoah, it was not equipped to return unused heap memory to the operating system. Java 13 added this capability to the ZGC.

Z垃圾收集器在Java 11中被引入,作为一种低延迟的垃圾收集机制,这样GC的暂停时间就不会超过10ms。然而,与其他HotSpot VM GC(如G1和Shenandoah)不同,它不具备将未使用的堆内存返回给操作系统的能力。Java 13 为 ZGC 增加了这一功能

We now get a reduced memory footprint along with performance improvement.

我们现在得到了一个减少的内存足迹,同时性能也得到了提高。

Starting with Java 13, the ZGC now returns uncommitted memory to the operating system by default, up until the specified minimum heap size is reached. If we do not want to use this feature, we can go back to the Java 11 way by:

从Java 13开始,ZGC现在默认将未承诺的内存返回给操作系统,直到达到指定的最小堆大小。如果我们不想使用这个功能,我们可以回到Java 11的方式。

  • Using option -XX:-ZUncommit, or
  • Setting equal minimum (-Xms) and maximum (-Xmx) heap sizes

Additionally, ZGC now has a maximum supported heap size of 16TB. Earlier, 4TB was the limit.

此外,ZGC现在的最大支持堆大小为16TB。早些时候,4TB是极限。

5. Reimplement the Legacy Socket API (JEP 353)

5.重新实现传统的Socket API(JEP 353)

We have seen Socket (java.net.Socket and java.net.ServerSocket) APIs as an integral part of Java since its onset. However, they were never modernized in the last twenty years. Written in legacy Java and C, they were cumbersome and difficult to maintain.

我们已经看到Socket(java.net.Socketjava.net.ServerSocket)API自Java诞生以来就是其不可或缺的一部分。然而,在过去的二十年里,它们从未被现代化过。它们是用传统的Java和C语言编写的,非常繁琐且难以维护。

Java 13 bucked this trend and replaced the underlying implementation to align the API with the futuristic user-mode threads. Instead of PlainSocketImpl, the provider interface now points to NioSocketImpl. This newly coded implementation is based on the same internal infrastructure as java.nio.

Java 13 违背了这一趋势,替换了底层实现,使 API 与未来的用户模式线程保持一致。现在,提供者接口不再是PlainSocketImpl,而是指向NioSocketImpl。这个新编码的实现是基于与java.nio相同的内部基础架构。

Again, we do have a way to go back to using PlainSocketImpl. We can start the JVM with the system property -Djdk.net.usePlainSocketImpl set as true to use the older implementation. The default is NioSocketImpl.

同样,我们确实有办法回到使用PlainSocketImpl。我们可以在启动 JVM 时将系统属性 -Djdk.net.usePlainSocketImpl 设置为 true 来使用旧的实现。默认的是NioSocketImpl.

6. Miscellaneous Changes

6.杂项修改

Apart from the JEPs listed above, Java 13 has given us a few more notable changes:

除了上面列出的JEP之外,Java 13还给我们带来了一些值得注意的变化。

  • java.nio – method FileSystems.newFileSystem(Path, Map<String, ?>) added
  • java.time – new official Japanese era name added
  • javax.crypto – support for MS Cryptography Next Generation (CNG)
  • javax.security – property jdk.sasl.disabledMechanisms added to disable SASL mechanisms
  • javax.xml.crypto – new String constants introduced to represent Canonical XML 1.1 URIs
  • javax.xml.parsers – new methods added to instantiate DOM and SAX factories with namespaces support
  • Unicode support upgraded to version 12.1
  • Support added for Kerberos principal name canonicalization and cross-realm referrals

Additionally, a few APIs are proposed for removal. These include the three String methods listed above, and the javax.security.cert API.

此外,有几个 API 是建议删除的。这些方法包括上面列出的三个String方法,以及javax.security.cert API。

Among the removals include the rmic tool and old features from the JavaDoc tool. Pre-JDK 1.4 SocketImpl implementations are also no longer supported.

删除的内容包括rmic工具和JavaDoc工具的旧功能。JDK 1.4之前的SocketImpl实现也不再被支持。

7. Conclusion

7.结语

In this article, we saw all five JDK Enhancement Proposals implemented by Java 13. We also listed down some other notable additions and deletions.

在这篇文章中,我们看到了Java 13实现的所有五个JDK增强建议。我们还列举了其他一些值得注意的增删内容。

As usual, source code is available over on GitHub.

像往常一样,源代码可在GitHub上获得over