JavaRush /Java 博客 /Random-ZH /从 8 到 13:Java 版本的完整概述。第2部分

从 8 到 13:Java 版本的完整概述。第2部分

已在 Random-ZH 群组中发布
本文是我对 Java 版本 8-13 中的创新回顾的第二部分。第一部分在这里。话不多说,让我们继续看:2018 年 9 月 25 日,新版 JDK 发布:

爪哇11

从 8 到 13:Java 版本的完整概述。 第 2 - 1 部分

var(以 lambda 为单位)

从现在开始,我们可以在编写 lambda 表达式(隐式类型 lambda 表达式)时指定 lambda 参数的类型或省略它们:
Function<String, String> append = (var string) -> string + " Text";
String appendedString = append.apply("Some");
System.out.println(appendedString);
您还可以向 lambda 参数添加注释,而无需编写完整的变量类型名称:
Function<String, String> append = (@NonNull var string) -> string + " Text";

Z(ZGC)

ZGC是一个新的垃圾收集器,不起作用。它分配新内存但从不重新启动它。ZGC 承诺以高吞吐量和低延迟管理大量内存(ZGC 仅在 64 位平台上可用)。参考着色 - ZGC 使用 64 位指针以及称为指针着色的技术。彩色指针存储有关堆上对象的附加信息。当内存变得碎片化时,这有助于避免 GC 需要为新分配寻找空间时性能下降。使用 ZGC 的垃圾收集包括以下步骤:
  1. 世界站:我们寻找到达堆上对象的起点(例如局部变量或静态字段);
  2. 从根链接开始的对象图的交集。我们标记我们到达的每个对象(ZGC 遍历对象图并检查彩色标记,标记可用对象);
  3. 处理一些边缘情况,例如薄弱环节;
  4. 移动活动对象,释放大面积的堆以加速分配。
  5. 当移动阶段开始时,ZGC 将堆拆分为页面并一次处理一页;
  6. ZGC 完成任何根部的运动,然后进行其余的运动。
这个话题非常复杂且令人困惑。详细的讨论需要单独的文章,所以我就放在这里:

埃普西隆气相色谱仪

Epsilon 是一个垃圾收集器,它处理内存分配,但不实现任何真正的内存回收机制。一旦可用的 Java 堆耗尽,JVM 将关闭。也就是说,如果您开始在无限数组中创建对象而不使用此垃圾收集器绑定到引用,则应用程序将因OutOfMemoryError崩溃(如果使用任何其他错误,则不会崩溃,因为它将清理没有引用的对象) 。为什么需要它?原因如下:
  1. 性能测试。
  2. 内存压力测试。
  3. 测试虚拟机接口。
  4. 工作时间极短。
  5. 最后下降延迟改进。
  6. 最后一滴吞吐量的改进。
有用的链接: 其他创新:
  1. ByteArrayOutputStream有一个方法void writeBytes(byte [])将参数中的所有字节写入OutputStream.
  2. FileReaderFileWriter获得了新的构造函数,允许您指定字符集。
  3. Path抓住了两个新方法,从字符串参数of(String, String [])返回路径或字符串序列,组合起来形成路径字符串,并且:从 URI 返回路径。Pathof(URI)
  4. Pattern- 收到一个方法asMatchPredicate(),用于检查给定的输入字符串是否与给定的模式匹配(是否允许您使用正则表达式创建谓词,以便您可以过滤流中的数据)。
  5. String我学到了很多有用的方法,例如:
    • String strip():将返回一个字符串,即该字符串,删除字符串开头和结尾的所有空格(类似于trim(),但定义空格不同);
    • String stripLeading(): 将返回该字符串,并删除该字符串中的所有前导空格;
    • String stripTrailing(): 将返回该字符串,删除字符串末尾的所有空格;
    • Stream lines()Stream: 将从中返回String,从该字符串中提取,用行分隔符分隔;
    • String repeat(int): 将返回一个字符串,该字符串是该字符串的串联,重复多次。
    • boolean isBlank(): 如果字符串为空或仅包含空格,则返回 true,否则返回 false。
  6. Thread— 方法 destroy() 和 stop(Throwable) 已被删除。
  7. Files获得了一些新方法:
    • String readString(Path):将文件中的所有数据读取到字符串中,同时使用 UTF-8 编码从字节解码为字符;
    • String readString(Path, Charset):与上面的方法相同,区别是使用指定的 Charset 从字节解码为字符;
    • Path writeString (Path, CharSequence, OpenOption []):将字符序列写入文件。使用UTF-8编码将字符编码为字节;
    • Path writeString(Path, CharSequence,Charset, OpenOption []):与上面的方法相同,只是使用Charset中指定的编码将字符编码为字节。
这些是最有趣的 API 创新(以我的拙见),这里有一些材料可供更详细的审查:

爪哇12

六个月过去了,我们看到了 Java 发展的下一阶段。所以,是时候拿出一把知识铲子来挖掘了。 从 8 到 13:Java 版本的完整概述。 第 2 - 2 部分

更新G1

G1 进行了以下改进:
  1. 回收未使用的已分配内存

    在 Java 堆内存中,存在未使用内存(或者换句话说,不活动内存)这样的东西。在 Java 12 中,他们决定解决这个问题,现在:

    • G1 在完整 GC 或并行循环期间从堆返回内存;G1 尝试阻止 Full GC,并根据堆分配启动并行循环。我们必须强制 G1 从堆中返回内存。

    此改进侧重于性能,在 G1 未使用时自动将内存从堆返回到操作系统。

  2. 超过暂停时间时中止混合收集

    G1使用分析引擎来选择垃圾收集所需的工作量。它在定义集合并开始清理后不间断地收集活动对象。这会导致垃圾收集器超出其暂停时间目标。实际上,这个问题通过改进就解决了,因为如果完成下一步所需的时间超出合理限度,则可以中断此步骤。

微基准测试

Java 12 引入了微基准测试,以便可以使用现有基准轻松测试 JVM 性能。这对于任何想要使用 JVM 本身的人来说都非常有用。添加的测试是使用 Java Microbenchmark Harness (JMH) 创建的。这些测试允许对 JVM 进行持续的性能测试。JEP 230 建议引入大约 100 个测试,并随着 Java 新版本的发布而引入新的测试。下面是添加的测试的示例

谢南多厄

这是一种垃圾收集 (GC) 算法,旨在保证低响应时间(下限为 10-500 毫秒)。这可以减少在运行 Java 线程的同时进行清理工作时的 GC 暂停时间。在 Shenandoah 中,暂停时间与堆大小无关。这意味着无论堆的大小如何,暂停时间都是相同的。这是一项实验性功能,不包含在 OpenJDK 的标准 (Oracle) 版本中。

改进开关

Java 12 改进了用于模式匹配的 Switch 表达式。引入了新语法 L → 。以下是新开关的要点列表
  1. 新语法不再需要使用break语句来防止错误。
  2. Switch 表达式不再失败。
  3. 此外,我们可以在单个标签中定义多个常量。
  4. switch 表达式中现在需要 default case。
  5. break 在 Switch 表达式中用于从寄存器本身返回值(实际上,switch 可以返回值)。
让我们看一下这个例子:
var result = switch (someDay) {
  case "M", "W", "F" -> "MWF";
  case "T", "TH", "S" -> "TTS";
  default -> {
      if(someDay.isEmpty())
            break "Please insert a valid day.";
      else
            break "Looks like a Sunday.";
  }
};
Java 13 中切换表达式的权威指南 其他新功能:
  1. String:

    transform(Function f)- 将提供的函数应用于字符串。结果可能不是字符串。
    indent(int x)— 向字符串添加 x 个空格。如果参数为负数,则将删除此数量的前导空格(如果可能)。

  2. Files- 获取类似 的方法mismatch(),该方法依次查找并返回两个文件内容中第一个不匹配字节的位置,如果没有不匹配,则返回 -1L。

  3. 出现了一个新类 -CompactNumberFormat用于以紧凑形式格式化十进制数。这种紧凑形式的一个例子是 1M 而不是 1,000,000。因此,只需要两个 2 而不是 9 个字符。

  4. 还有一种新的 enumNumberFormatStyle它有两个值——LONG 和 SHORT。

  5. InputStream 得到的方法是 skipNBytes(long n):从输入流中跳过第n个字节。

有趣的 Java 12 链接:

爪哇13

世界不是静止的,它在移动,它在发展,就像 Java - Java 13 一样。 从 8 到 13:Java 版本的完整概述。 第 2 - 3 部分

文本块

Java 在定义字符串方面总是遇到一些麻烦。如果我们需要定义带有空格、换行符、引号或其他内容的行,这会造成一些困难,因此我们必须使用特殊字符:例如,\n 表示换行符,或转义某些行本身。这显着降低了代码的可读性,并且在编写这样的行时需要额外的时间。当编写显示 JSON、XML、HTML 等的字符串时,这一点变得尤其明显。结果,如果我们想写一个小的 Json,它会看起来像这样:
String JSON_STRING = "{\r\n" + "\"name\" : \"someName\",\r\n" + "\"site\" : \"https://www.someSite.com/\"\r\n" + "}";
然后 Java 13 出现了,并以文本前后的三个双引号(他们称之为文本块)的形式为我们提供了解决方案。让我们看一下前面使用此创新的 json 示例:
String TEXT_BLOCK_JSON = """
{
    "name" : "someName",
    "site" : "https://www.someSite.com/"
}
""";
更简单、更清晰,不是吗?还分别添加了String三种新方法 来管理这些块:
  • stripIndent():从字符串中删除随机空格。如果您正在读取多行字符串并希望应用与显式声明相同的随机空白排除(本质上是模拟编译器删除随机空白),这非常有用;
  • formatted(Object... args ):与 类似format(String format, Object... arg),但用于文本块;
  • translateEscapes():返回一个字符串,其中转义序列(例如 \r)转换为相应的 Unicode 值。

改进开关

Switch 表达式是在 Java 12 中引入的,并在 13 中对其进行了改进。在12中你使用break定义返回值。13中,返回值被yield替代。现在,我们在 Java 12 部分中的 switch 表达式可以重写为:
var result = switch (someDay) {
  case "M", "W", "F" -> "MWF";
  case "T", "TH", "S" -> "TTS";
  default -> {
      if(someDay.isEmpty())
          yield "Please insert a valid day.";
      else
          yield "Looks like a Sunday.";
  }
};
虽然对于我们这些已经熟悉Java的程序员来说接受break是很正常的事情,但是却又很奇怪。Break true想告诉我什么?新的(相对较新的)yield关键字更加清晰,并且将来可能会出现在其他返回值的地方。对于那些对此主题非常感兴趣的人,我建议您熟悉以下材料:

动态 CDS 档案

CDS - 类数据共享。允许您将一组常用的类打包到一个存档中,稍后可以由多个 JVM 实例加载。我们为什么需要这个?事实是,在加载类的过程中,JVM做了相当多的资源密集型动作,比如读取类、将其存储在内部结构中、检查读取的类的正确性、搜索并加载依赖类等.,只有在这一切之后,类才准备好工作。可以理解的是,由于 JVM 实例经常加载相同的类,因此浪费了大量资源。例如字符串、链接列表、整数。好吧,或者同一应用程序的类,所有这些都是资源。如果我们只执行一次所有必要的步骤,然后将重新设计的类放入一个可以加载到多个 JVM 内存中的存档中,这可以显着节省内存空间并减少应用程序启动时间。实际上,CDS 使得创建这样的存档成为可能。Java 9 只允许将系统类添加到存档中。Java 10 - 在存档中包含应用程序类。 此类档案的创建包括:
  • 创建应用程序加载的类列表;
  • 用我们找到的类创建一个急需的档案。
Java 13 中的创新改进了 CDS,以便它可以在应用程序终止时创建存档。这意味着上述两个步骤现在将合二为一。更重要的一点是:只有在应用程序运行时加载的类才会添加到存档中。换句话说,那些仍包含在 application.jar 中但由于某种原因未加载的类将不会添加到存档中。

更新套接字API

Socket API(java.net.Socket 和 java.net.ServerSocket)本质上是 Java 自诞生以来不可或缺的一部分,但套接字在过去二十年中从未更新过。它们是用 C 和 Java 编写的,非常非常庞大且难以维护。但 Java 13 决定对整个问题进行自己的调整并替换了基本实现。现在,提供者接口已替换为NioSocketImpl ,而不是 PlainSocketImpl这个新的编码实现基于与java.nio相同的后端基础设施。本质上,该类使用 java.util.concurrent 缓冲区缓存和锁定机制(基于段)而不是同步方法。它不再需要本机代码,从而更容易移植到不同的平台。尽管如此,我们还是有办法恢复使用PlainSocketImpl,但从现在开始默认使用NioSocketImpl

ZGC 的内存返回

我们记得,Z 垃圾收集器是在 Java 11 中引入的,作为一种低延迟垃圾收集机制,因此 GC 暂停永远不会超过 10 毫秒。但与此同时,与其他虚拟 GC 热点(例如 Shenandoah 和 G1)不同,它可以将未使用的动态内存返回给操作系统。此修改将 J 功能添加到 ZGC。因此,我们减少了内存占用并提高了性能,并且 ZGC 现在默认将未提交的内存返回给操作系统,直到达到指定的最小堆大小。还有一件事:ZGC 现在支持的最大堆大小为 16 TB。此前,4TB 是限制。 其他创新:
  1. javax.security- 添加了一个属性jdk.sasl.disabledMechanisms来禁用 SASL 机制。
  2. java.nio- 添加了一种方法FileSystems.newFileSystem (Path, Map <String,?>)- 分别创建新文件。
  3. java.nio现在具有绝对(而不是相对)getset- 方法。它们与抽象基类一样,包含用于检索部分缓冲区的Buffer方法。slice()
  4. 添加了javax.xml.parsers用于实例化 DOM 和 SAX 工厂的方法(具有命名空间支持)。
  5. Unicode 支持已更新至版本 12.1。
关于 Java 13 的有趣链接:

结果

我们可以回顾一下 Java 14 中已宣布的创新,但由于它很快就会亮相 - JDK 14 计划于 2020 年 3 月 17 日发布,因此最好在发布后立即对其进行单独、全面的审查。我还想提请您注意这样一个事实:在其他版本之间间隔较长的编程语言中,例如Python 2-3,不存在兼容性:也就是说,如果代码是用Python 2编写的,您将需要努力将其翻译为3。Java在这方面很特别,因为它具有极强的向后兼容性。这意味着您的 Java 5 或 8 程序保证可以在 Java 8-13 虚拟机上运行,​​但有一些例外情况您暂时无需担心。显然,反之则不行:例如,如果您的应用程序使用 Java 13 函数,而这些函数在 Java 8 JVM 中根本不可用。这就是我今天的全部内容,尊重那些读到这里的人)) 从 8 到 13:Java 版本的完整概述。 第 2 - 5 部分
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION