Java 10 功能
Java 10 是 Java 23 年历史上发布速度最快的版本。Java 一直因其发展和演进缓慢而受到批评,但 Java 10 打破了这一观念。Java 10 是一个具有许多未来性变化的版本,其范围和影响可能并不明显,但却是深远的。在本文中,我们将讨论 Java10 版本中添加的各种功能。在此之前,让我们先了解一下 Java 发布模型中引入的一些变化。
长期支持模式
从 2017 年开始,Oracle 和 Java 社区宣布将 Java 的发布周期改为每 6 个月一次。Oracle Java SE 产品将采用长期支持 (LTS) 模式。这意味着什么? Oracle 会为该产品提供优质和持续的支持,目标是每 3 年发布一次。每个 Java 版本都以一两个主要功能为蓝本,这些功能推动了发布。任何障碍都会推迟发布并延迟上市。Project Jigsaw 是 Java 9 的主要功能,它几次推迟了发布日期,并且发布时间被推迟了 1.5 年以上。每 6 个月一次的发布节奏将遵循发布列车。发布列车每 6 个月有一个时间表。符合要求的功能将登上列车;否则,它们将等待下一趟预定的列车。
Oracle JDK 与 Open JDK
为了更加方便开发人员,Oracle 和 Java 社区现在推广 OpenJDK 二进制文件作为今后的主要 JDK。这与以前相比是一个很大的进步,那时的 JDK 二进制文件是 Oracle 专有和授权的,对重新分发有各种限制。不过,Oracle 将继续生产他们的 JDK,但仅限于长期支持版本。这是朝着更加云和容器友好的方向迈出的一步,因为开放的 JDK 二进制文件可以作为容器的一部分进行分发。这意味着什么?开放的 JDK 二进制文件将每 6 个月发布一次,而 Oracle JDK 二进制文件将每 3 年发布一次(LTS 版本)。哪些 JDK 二进制文件将被采用?大型组织需要时间在版本之间转换;他们会一直使用这个版本,直到可以转换为止。业界对 Java 6 的采用多于 Java 7,然后业界正在逐渐转向Java 8。在我看来,LTS 版本将是最受企业青睐的版本。但是,它是否会是 Oracle JDK 或 Open JDK 的 LTS 版本尚不清楚,部分原因是云空间中有很多事情要做。Java 9和 10 不是 LTS 版本。将于 2018 年 9 月发布的 Java 11 将是 LTS 版本。
Java 10 功能
让我们先睹为快 Java 10 中的功能。
随着基于时间的发布周期的采用,Oracle 更改了 Java SE 平台和 JDK 的版本字符串方案以及相关的版本信息,以适应现在和将来的基于时间的发布模型。版本号的新模式是:$FEATURE.$INTERIM.$UPDATE.$PATCH
$FEATURE:计数器每 6 个月递增一次,并基于功能发布版本,例如:JDK 10、JDK 11。$INTERIM:对于包含兼容错误修复和增强但没有不兼容更改的非功能版本,计数器将递增。通常,它将为零,因为六个月内不会有临时版本。这保留用于发布模型的未来修订。$UPDATE:对于修复安全问题、回归和新功能中的错误的兼容更新版本,计数器将递增。这在功能发布后一个月更新,此后每 3 个月更新一次。 2018 年 4 月发布的版本是 JDK 10.0.1,7 月发布的版本是 JDK 10.0.2,依此类推,$PATCH:计数器将增加,以便紧急发布以修复关键问题。已添加新 API 以通过编程方式获取这些计数器值。让我们来看看;
Version version = Runtime.version();
version.feature();
version.interim();
version.update();
version.patch();
现在,让我们看一下返回版本信息的 Java 启动器:
$ java -version
java version "10" 2018-03-20
Java(TM) SE Runtime Environment 18.3 (build 10+46)
Java HotSpot(TM) 64-Bit Server VM 18.3 (build 10+46, mixed mode)
版本号格式为“10”,因为没有其他计数器不是零。添加了发布日期。18.3 可以读作 2018 年和第 3 个月,版本 10+46 是版本 10 的第 46 个版本。对于 JDK 10.0.1 的假设版本 93,版本将是 10.0.1+939。### 局部变量类型推断 (JEP 286)
局部变量类型推断是 Java 10 中对开发者来说最大的新功能。它为具有初始化器的局部变量声明添加了类型推断。局部类型推断只能在以下场景中使用:
- 仅限于具有初始化程序的局部变量
- 增强 for 循环或索引的索引
- for 循环中声明的局部
我们来看看它的用法:
var numbers = List.of(1, 2, 3, 4, 5); // inferred value ArrayList<String>
// Index of Enhanced For Loop
for (var number : numbers) {
System.out.println(number);
}
// Local variable declared in a loop
for (var i = 0; i < numbers.size(); i++) {
System.out.println(numbers.get(i));
}
您可以在我们关于Java 10 局部变量类型推断的独家文章中阅读更多相关信息。13.### 基于 Java 的实验性 JIT 编译器(JEP 317)
此功能使基于 Java 的 JIT 编译器 Graal 可用作 Linux/x64 平台上的实验性 JIT 编译器。这是 Java 10 功能列表中迄今为止最具未来感的功能。Graal 是在 Java 9 中引入的。它是我们习惯的 JIT 编译器的替代品。它是 JVM 的一个插件,这意味着 JIT 编译器与 JVM 无关,可以动态插入并替换为任何其他符合 JVMCI(Java 级 JVM 编译器接口)的插件。它还在 Java 世界中带来了提前 (AOT) 编译。它还支持多语言解释。“用 Java 编写的基于 Java 的即时编译器,用于将 Java 字节码转换为机器码。”这令人困惑吗?如果 JVM 是用 Java 编写的,那么您不需要 JVM 来运行 JVM 吗?可以对 JVM 进行 AOT 编译,然后可以在 JVM 中使用 JIT 编译器通过实时代码优化来提高性能。 Graal 是使用 Java 从头开始完全重写的 JIT 编译器。以前的 JIT 编译器是用 c++ 编写的。它被认为是任何编程语言进化的最后阶段之一。您可以使用以下 jvm 参数切换到 Graal:
-XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler
您可以从Chris Seaton 的演讲.16中了解有关 Graal 的更多信息。### 应用程序类数据共享 (JEP 310)
此功能有助于改善启动占用空间,扩展了现有的类数据共享(“CDS”)功能以允许将应用程序类放置在共享存档中。 JVM 在启动时执行一些初步步骤,其中之一是将类加载到内存中。 如果有多个 jar 包含多个类,那么第一个请求的滞后是显而易见的。 这成为无服务器架构的一个问题,因为启动时间至关重要。 为了缩短应用程序启动时间,可以使用应用程序类数据共享。 这个想法是通过在不同的 Java 进程之间共享通用类元数据来减少占用空间。 这可以通过以下 3 个步骤实现:确定要存档的类:使用 java 启动器创建要存档的文件列表,这可以通过以下参数实现:
$java -Xshare:off -XX:+UseAppCDS -XX:DumpLoadedClassList=hello.lst -cp hello.jar HelloWorld
创建 AppCDS 档案:使用 java 启动器创建用于应用程序 CDS 的文件列表的档案,这可以通过以下参数实现:
$java -Xshare:dump -XX:+UseAppCDS -XX:SharedClassListFile=hello.lst -XX:SharedArchiveFile=hello.jsa -cp hello.jar
使用 AppCDS 存档:使用具有以下参数的 Java 启动器来使用应用程序 CDS。
$java -Xshare:on -XX:+UseAppCDS -XX:SharedArchiveFile=hello.jsa -cp hello.jar HelloWorld
G1垃圾收集器在 JDK 9 中成为默认垃圾收集器。G1 垃圾收集器可避免任何完整的垃圾收集,但当用于收集的并发线程无法足够快地恢复内存时,用户体验会受到影响。此更改通过使完整 GC 并行化来改善 G1 最坏情况延迟。G1 收集器的标记-清除-压缩算法作为此更改的一部分并行化,当用于收集的并发线程无法足够快地恢复内存时将被触发。25. ### 垃圾收集器接口 (JEP 304)
此 JEP 是面向未来的变革。它通过引入通用垃圾收集器接口来改善不同垃圾收集器的代码隔离。此更改为内部 GC 代码提供了更好的模块化。它将有助于在不更改现有代码库的情况下添加新的 GC,也有助于删除或整理以前的 GC.26。### 附加 Unicode 语言标签扩展 (JEP 314)
此功能增强了 java.util.Locale 和相关 API,以实现 BCP 47 语言标签的其他 Unicode 扩展。从 Java SE 9 开始,支持的 BCP 47 U 语言标签扩展为“ca”和“nu”。此 JEP 将增加对以下其他扩展的支持:
- cu(货币类型)
- fw (一周的第一天)
- rg(区域覆盖)
- tz(时区)
为了支持这些附加扩展,对各种 API 进行了更改,以提供基于 U 或附加扩展的信息。
java.text.DateFormat::get*Instance
java.text.DateFormatSymbols::getInstance
java.text.DecimalFormatSymbols::getInstance
java.text.NumberFormat::get*Instance
java.time.format.DateTimeFormatter::localizedBy
java.time.format.DateTimeFormatterBuilder::getLocalizedDateTimePattern
java.time.format.DecimalStyle::of
java.time.temporal.WeekFields::of
java.util.Calendar::{getFirstDayOfWeek,getMinimalDaysInWeek}
java.util.Currency::getInstance
java.util.Locale::getDisplayName
java.util.spi.LocaleNameProvider
为了推广 OpenJDK 并使其对社区用户更具吸引力,此功能在 JDK 中提供了一组默认的根认证机构 (CA) 证书。这也意味着 Oracle 和 Open JDK 二进制文件在功能上将相同。未来,TLS 等关键安全组件将在 OpenJDK 版本中默认运行。30. ### 线程本地握手 (JEP 312)
这是 JVM 内部功能,用于提高性能。握手操作是针对每个 JavaThread 执行的回调,该回调在该线程处于安全点状态时执行。回调由线程本身或 VM 线程执行,同时保持线程处于阻塞状态。此功能提供了一种在线程上执行回调的方法,而无需执行全局 VM 安全点。使停止单个线程(而不仅仅是所有线程或不停止任何线程)成为可能且成本低廉。31. ### 备用内存设备上的堆分配 (JEP 316)
应用程序的内存需求越来越大,云原生应用程序、内存数据库和流媒体应用程序的数量都在增加。为了满足这些服务的需求,有各种内存架构可供选择。此功能增强了 HotSpot VM 在用户指定的备用内存设备(如 NV-DIMM)上分配 Java 对象堆的能力。此 JEP 针对具有与 DRAM 相同语义(包括原子操作语义)的备用内存设备,因此可以代替 DRAM 用于对象堆,而无需对现有应用程序代码进行任何更改。32. ### 删除 Native-Header 生成工具 – javah(JEP 313)
这是一项内部更改,旨在从 JDK 中删除 javah 工具。该工具功能是作为 JDK 8 的一部分添加的javac
,它提供了在编译时编写本机头文件的能力,从而使其变得javah
无用。35. ### 将 JDK Forest 整合到单个存储库中 (JEP 296)
多年来,JDK 代码库中存在各种 Mercurial 存储库。不同的存储库确实提供了一些优势,但它们也有各种操作缺点。作为此更改的一部分,JDK 森林中的众多存储库被合并为一个存储库,以简化和简化开发。36. ### API 更改
Java 10 添加和删除了(是的,这不是拼写错误)API。Java 9 引入了增强的弃用功能,其中某些 API 被标记为将在未来版本中删除。已删除的 API :您可以在此处找到已删除的 API 。已添加的 API :Java 10 中添加了 73 个新 API。您可以在此处找到已添加的 API 以及比较。让我们来看看一些新增内容:
- List、Map 和 Set 接口添加了静态 copyOf(Collection) 方法。该方法返回一个包含所提供条目的不可修改的 List、Map 或 Set。对于 List,如果给定的 List 随后被修改,则返回的 List 将不会反映此类修改。
- Optional 及其原始变体获得方法 orElseThrow()。这与 get() 完全相同,但 java 文档指出,它是比 get() 更受欢迎的替代方案
- Collectors 类获取用于收集不可修改集合的各种方法(Set、List、Map)
List<String> actors = new ArrayList<>();
actors.add("Jack Nicholson");
actors.add("Marlon Brando");
System.out.println(actors); // prints [Jack Nicholson, Marlon Brando]
// New API added - Creates an UnModifiable List from a List.
List<String> copyOfActors = List.copyOf(actors);
System.out.println(copyOfActors); // prints [Jack Nicholson, Marlon Brando]
// copyOfActors.add("Robert De Niro"); Will generate an
// UnsupportedOperationException
actors.add("Robert De Niro");
System.out.println(actors);// prints [Jack Nicholson, Marlon Brando, Robert De Niro]
System.out.println(copyOfActors); // prints [Jack Nicholson, Marlon Brando]
String str = "";
Optional<String> name = Optional.ofNullable(str);
// New API added - is preferred option then get() method
name.orElseThrow(); // same as name.get()
// New API added - Collectors.toUnmodifiableList
List<String> collect = actors.stream().collect(Collectors.toUnmodifiableList());
// collect.add("Tom Hanks"); // Will generate an
// UnsupportedOperationException
结论
在本文中,我们介绍了 Java 10 的各种新功能。如果您认为这里遗漏了任何重要内容,请通过评论告诉我们。与往常一样,您可以在 GitHub 上查看完整代码。