Java 10 - 快速指南

Java 10 - 概述

Java 10 是 Java 发布节奏中的一个主要版本,于 2018 年 3 月 10 日发布。通过 Java 10,Oracle 将 Java 发布节奏更改为新模型,即 Oracle Java SE 产品的 6 个月发布节奏和 LTS 模型。LTS 模型代表长期支持模型。

从 Java 10 开始,Oracle 每 6 个月发布一个新版本的 Java,每个版本包含一到两个主要功能。Oracle 使用发布序列概念。每个发布系列计划为期 6 个月。在此时间表内开发的功能将在版本中提供,否则功能将移至下一个版本系列。

Oracle JDK 与 OpenJDK

大多数 Oracle JDK 二进制文件都是 Oracle 专有的并获得许可,并且对重新分发有多种限制。而 OpenJDK 对开发者社区更加友好。从 Java 10 开始,Oracle 决定将 OpenJDK 推广为主要 JDK,以促进基于社区的 Java 开发。Oracle 将继续生产自己的 JDK,但会在 3 年后发布,并将其称为 LTS 版本。因此 OpenJDK 二进制文件将每六个月发布一次。

OpenJDK 对云和容器友好,因为它可以作为容器的一部分自由分发。所以Oracle推广OpenJDK的举动让java对于云或者容器的开发部署更加友好。

Java 9 和 Java 10 是非 LTS 版本。Java 11 版本是 LTS 版本。

新功能

以下是 Java 10 中引入的主要新功能。

  • JEP 286 - 局部变量类型推断

  • JEP 322 - 基于时间的发布版本控制

  • JEP 304 - 垃圾收集器接口

  • JEP 307 - G1 的并行完整 GC

  • JEP 316 - 替代内存设备上的堆分配

  • JEP 296 - 将 JDK 森林合并到单个存储库中

  • JEP 310 - 应用程序类数据共享

  • JEP 314 - 附加 Unicode 语言标签扩展

  • JEP 319 - 根证书

  • JEP 317 - 基于 Java 的实验性 JIT 编译器

  • JEP 312 - 线程局部握手

  • JEP 313 - 删除本机标头生成工具

  • JEP 319 - 根证书

  • JEP 319 - 根证书

Java 10 通过新方法和选项增强了 70 多个 API,并删除了已弃用的 API 和选项。我们将在接下来的章节中看到这些变化。

Java 10 - 环境设置

在线现场演示选项

我们已经在线设置了Java编程环境,以便您可以在线编译和执行所有可用的示例。它使您对所阅读的内容充满信心,并使您能够使用不同的选项验证程序。请随意修改任何示例并在线执行。

使用以下示例代码框右上角的“实时演示”选项尝试以下示例 -

public class MyFirstJavaProgram {
   public static void main(String []args) {
      System.out.println("Hello World");
   }
}

对于本教程中给出的大多数示例,您将在我们网站右上角的代码部分中找到“实时演示”选项,该选项将带您进入在线编译器。因此,请充分利用它并享受学习的乐趣。

本地环境设置

如果您想设置自己的 Java 编程语言环境,那么本节将指导您完成整个过程。请按照以下步骤设置您的 Java 环境。

Java SE 可供免费下载。要下载,请单击此处,请下载与您的操作系统兼容的版本。

按照说明下载 Java,然后运行​​.exe以在您的计算机上安装 Java。在计算机上安装 Java 后,您需要设置环境变量以指向正确的安装目录。

设置 Windows 2000/XP 的路径

假设您已将 Java 安装在 c:\Program Files\java\jdk 目录中 -

  • 右键单击“我的电脑”并选择“属性”。

  • 单击“高级”选项卡下的“环境变量”按钮。

  • 现在,编辑“Path”变量并在其末尾添加 Java 可执行文件目录的路径。例如,如果路径当前设置为C:\Windows\System32,则按以下方式编辑它

    C:\Windows\System32;c:\Program Files\java\jdk\bin

设置Windows 95/98/ME的路径

假设您已将 Java 安装在 c:\Program Files\java\jdk 目录中 -

  • 编辑“C:\autoexec.bat”文件并在末尾添加以下行 -

    设置路径=%PATH%;C:\Program Files\java\jdk\bin

设置 Linux、UNIX、Solaris、FreeBSD 的路径

应将环境变量 PATH 设置为指向 Java 二进制文件的安装位置。如果您在执行此操作时遇到问题,请参阅您的 shell 文档。

例如,如果您使用 bash 作为 shell,那么您可以在.bashrc末尾添加以下行-

  • 导出 PATH=/path/to/java:$PATH'

流行的 Java 编辑器

要编写 Java 程序,您需要一个文本编辑器。市场上还有更复杂的 IDE。最流行的简要描述如下 -

  • 记事本- 在 Windows 计算机上,您可以使用任何简单的文本编辑器,例如记事本(本教程推荐)或写字板。Notepad++ 也是一个免费的文本编辑器,增强了功能。

  • Netbeans - 它是一个开源且免费的 Java IDE,可以从https://www.netbeans.org/index.html下载。

  • Eclipse - 它也是由 Eclipse 开源社区开发的 Java IDE,可以从https://www.eclipse.org/下载。

IDE或集成开发环境,提供所有常见的工具和设施来帮助编程,例如源代码编辑器、构建工具和调试器等。

Java 10 - 基于时间的发布版本控制

从 Java 10 开始,Oracle 为 Java 版本引入了严格的基于时间的版本控制模型。现在,Java 每六个月就会发布一个主要版本。Java 10 于 2018 年 3 月发布,今后所有主要版本都计划在未来几年的 3 月和 9 月发布。版本进一步分为三大类。

  • 功能版本- 功能版本包含特定于语言的功能、JVM 功能、新的/改进的 API、API 的删除/弃用。这些功能发布的时间是固定的,并且对特定版本中包含的功能没有限制。如果正在开发的功能不是最新版本的一部分,那么它将计划在下一个版本中。

  • 更新版本- 更新版本包括错误修复、安全问题修复、回归修复等。每个更新版本计划于一月、四月、七月和十月每季度发布。在宣布下一个功能版本之前,每个功能版本将收到两个更新版本。

  • 长期支持 (LTS) 版本- 从 2018 年 9 月开始,将每三年发布一次长期支持版本。Oracle 将在未来三年内为此版本提供支持和更新。此版本主要面向在生产部署中使用 Java 的企业。

版本格式

现在的版本遵循以下格式。

$FEATURE.$INTERIM.$UPDATE.$PATCH

在哪里

  • $FEATURE - 该数字表示主要功能发布,并且在每个功能发布后都会增加 1。对于 Java 10,该值为 10。

  • $INTERIM - 该数字表示任何包含错误修复和增强功能的非功能、非更新版本。此版本没有任何不兼容的更改、任何 API 删除或对标准 API 的更改。功能发布后,此计数器将为 0。

  • $UPDATE - 此数字表示功能发布后完成的更新版本。例如,2018 年 4 月的 Java 更新版本是 JDK 10.0.1,2018 年 7 月的更新版本是 JDK 10.0.2,依此类推。

  • $PATCH - 该数字表示仅在紧急情况下升级关键问题时才增加的任何紧急版本。

例子

以下程序显示了 JAVA 10 的版本控制详细信息。

public class Tester {
   public static void main(String[] args) {
      Runtime.Version version = Runtime.version();
      System.out.printf(" feature: %s%n interim: %s%n update: %s%n patch: %s%n",
         version.feature(), 
         version.interim(), 
         version.update(), 
         version.patch());
   }
}

输出

它将打印以下输出。

feature: 10
interim: 0
update: 2
patch: 0

Java 10 - 局部变量类型推断

JEP 286 - 局部变量类型推断

局部变量类型推断是 Java 10 以来最明显的语言变化之一。它允许使用 var 定义变量而不指定它的类型。编译器使用提供的值推断变量的类型。这种类型推断仅限于局部变量。

声明局部变量的旧方法。

String name = "Welcome to tutorialspoint.com";

声明局部变量的新方法。

var name = "Welcome to tutorialspoint.com";

现在,编译器通过检查提供的值将 name 变量的类型推断为 String。

值得注意的点

  • 成员变量、方法参数、返回值不进行类型推断。

  • 局部变量应在声明时初始化,否则编译器将无法推断并抛出错误。

  • 局部变量推断可在循环语句的初始化块内使用。

  • 没有运行时开销。由于编译器根据提供的值推断类型,因此不会有性能损失。

  • 没有动态类型变化。一旦推断出局部变量的类型,就无法更改。

  • 使用局部变量类型推断可以减少复杂的样板代码。

Map<Integer, String> mapNames = new HashMap<>();

var mapNames1 = new HashMap<Integer, String>();

例子

以下程序展示了 JAVA 10 中局部变量类型推断的使用。

import java.util.List;

public class Tester {
   public static void main(String[] args) {
      var names = List.of("Julie", "Robert", "Chris", "Joseph"); 
      for (var name : names) {
         System.out.println(name);
      }
      System.out.println("");
      for (var i = 0; i < names.size(); i++) {
         System.out.println(names.get(i));
      }
   }
}

输出

它将打印以下输出。

Julie
Robert
Chris
Joseph

Julie
Robert
Chris
Joseph

Java 10 - 新 API 和选项

JDK 10 版本向 Java 库添加了 70 多个新 API 和选项。以下是引入的一些重要增强功能。

可选.orElseThrow() 方法

java.util.Optional 类中提供了一个新方法orElseThrow() ,它现在是get()方法的首选替代方法。

用于创建不可修改集合的 API

List、Set 和 Map 接口中提供了一种新方法copyOf() ,它可以从现有集合实例创建新的集合实例。Collector 类具有新方法toUnmodifyingList()、toUnmodifyingSet() 和 toUnmodifyingMap(),用于将流的元素获取到不可修改的集合中。

禁用 JRE 上次使用情况跟踪

引入了一个新标志 jdk.disableLastUsageTracking,它禁用正在运行的 VM 的 JRE 最后使用情况跟踪。

哈希密码

jmxremote.password 文件中可用的纯文本密码现在被 JMX 代理用其 SHA3-512 哈希值覆盖。

javadoc 对多个样式表的支持

javadoc 命令可以使用一个新选项 --add-stylesheet。此选项支持在生成的文档中使用多个样式表。

javadoc 对重写方法的支持

javadoc 命令可以使用一个新选项 --overridden-methods=value。许多类会重写继承的方法,但不会更改规范。--overridden-methods=value 选项允许将这些方法与其他继承的方法分组,而不是再次单独记录它们。

javadoc 对摘要的支持

新的内联标记 {@summary ...} 可用于指定用作 API 描述摘要的文本。默认情况下,API 描述的摘要是从第一句话推断出来的。

例子

以下程序展示了 JAVA 10 中一些新 API 的使用。

import java.util.List;
import java.util.stream.Collectors;

public class Tester {
   public static void main(String[] args) {
      var ids = List.of(1, 2, 3, 4, 5); 
      try {
         // get an unmodifiable list
         List<Integer> copyOfIds = List.copyOf(ids);
         copyOfIds.add(6);	
      } catch(UnsupportedOperationException e){
         System.out.println("Collection is not modifiable.");
      }
      try{
         // get an unmodifiable list
         List<Integer> evenNumbers = ids.stream()
            .filter(i -> i % 2 == 0)
            .collect(Collectors.toUnmodifiableList());;
         evenNumbers.add(6);	
      }catch(UnsupportedOperationException e){
         System.out.println("Collection is not modifiable.");
      }
   }
}

输出

它将打印以下输出。

Collection is not modifiable.
Collection is not modifiable.

Java 10 - 删除的功能和选项

JDK 10 版本已从 Java 库中删除了多个已弃用的 API、功能和选项。以下为相关详情。

  • 删除了不支持的 LookAndFeels - 使用 Nimbus 或 Aqua LookAndFeels 的应用程序必须迁移到新语法。

Nimbus - 现有代码

javax.swing.UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");

Nimbus - 新代码

UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");

Aqua - 现有代码

javax.swing.UIManager.setLookAndFeel("apple.laf.AquaLookAndFeel");

Aqua - 新代码

UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
  • Runtime.getLocalizedInputStream 和 getLocalizedOutputStream 方法已删除- Runtime.getLocalizedInputStream 和 getLocalizedOutputStream 方法不再可用,因为它们是过时的国际化机制的一部分。

  • 删除了 RMI 服务器端多路复用协议支持- RMI 服务器端多路复用协议在 Java 9 中被禁用,并在 Java 10 中被删除。

  • 删除了常见 DOM API - com.sun.java.browser.plugin2.DOM 和 sun.plugin.dom.DOMObject API 已被删除。netscape.javascript.JSObject 可用于修改 DOM。

  • FlatProfiler 已删除- FlatProfiler 在 Java 9 中已弃用,并在 Java 10 中被删除。

  • 已删除过时的 -X 选项- -Xoss、-Xsqnopause、-Xoptimize、-Xboundthreads 和 -Xusealtsigs,过时的 Hotspot VM 选项已在 java 10 中删除。

  • HostServicesgetWebContext 方法已删除- HostServicesgetWebContext 方法在 Java 9 中已弃用,并在 Java 10 中删除。

  • 删除了 T2K 光栅器和 ICU 布局引擎- T2K 光栅器和 ICU 布局引擎已从 JavaFX 中删除。

  • VP6/FXM/FLV 代码已删除- P6 视频编码格式和 FXM/FLV 容器支持已在 JavaFX Media 中删除。将改用 MP4 容器中的 H.264/AVC1 或 HTTP Live Streaming。

  • 1.2 版之前的 SecurityManager 方法和字段已删除- 1.2 版之前已弃用的 java.lang.SecurityManager 方法和字段(标记为 forRemoval=true)已被删除。

  • 已删除policytool -policytool安全工具已被删除。

  • com.sun.security.auth.** 中已弃用的类已删除

    以下已弃用的类已被删除

    • com.sun.security.auth.PolicyFile

    • com.sun.security.auth.SolarisNumericGroupPrincipal

    • com.sun.security.auth.SolarisNumericUserPrincipal

    • com.sun.security.auth.SolarisPrincipal

    • com.sun.security.auth.X500Principal

    • com.sun.security.auth.module.SolarisLoginModule

    • com.sun.security.auth.module.SolarisSystem

  • 旧(JDK 6、JDK 7 和 JDK 8 时代)标准 Doclet 已删除- 旧(JDK 6、JDK 7 和 JDK 8 时代)标准 doclet 用于输出 HTML 内容,并已被替代品取代,已被删除。

  • javah 工具已删除- 本机标头生成工具 javah 已被删除。

  • Java 启动器的数据模型选项 -d32 和 -d64 已删除。− 已删除过时和已弃用的选择选项(-d32、-d64、-J-d32 和 -J-d64)。

Java 10 - 已弃用的功能和选项

JDK 10 版本已弃用 Java 库中的多个 API、功能和选项。以下为相关详情。

  • SNMP 监控支持已弃用- 支持 SNMP 监控和 JVM 管理支持的 jdk.snmp 模块现已弃用,并标记为 forRemoval=true。

  • java.security 类已弃用- java.security.{Certificate, Identity, IdentityScope, Signer} 类现已弃用,并标记为 forRemoval=true。

  • javax.security.auth.Policy API forRemoval - 已弃用的 javax.security.auth.Policy 标记为 forRemoval=true。

  • 标记为删除的 API - 以下 API 也标记为在 Java 10 版本中删除,因为独立实现很容易获得。

    • java.activation

    • java.corba

    • java.se.ee(聚合器)

    • java.transaction

    • java.xml.绑定

    • java.xml.ws

    • java.xml.ws.annotation

Java 10 - JIT 编译器

JEP 317 - 基于 Java 的实验性 JIT 编译器

JIT编译器是用C++编写的,用于将Java转换为字节码。现在,Java 10 可以选择启用基于 Java 的实验性 JIT 编译器 Graal,而不是使用标准 JIT 编译器。Graal 使用 JVMCI(Java 9 中引入的 JVM 编译器接口)。Graal 也可在 Java 9 中使用。借助 Java 10,我们可以启用 Graal 来测试和调试实验性 JVM 编译器。

句法

java -XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler

Graal 编译器是基于 C++ 的早期编译器的完全重写,针对基于 Linux/x64 的平台。Graal 是在 Java 9 中引入的,作为目前使用的 JIT 编译器的替代方案。Graal 是 JVM 的插件,可以动态插入。它还支持多语言解释。

风险和假设

由于 Graal 是实验性的,并且需要考虑各种热点和具有各种标志选项的 jdk 测试来进行测试工作。与标准 JIT 提前编译器相比,它可能无法通过某些性能基准测试。

Java 10 - 类数据共享

JEP 310 - 应用程序类数据共享

当 JVM 启动时,它会将类加载到内存中作为预备步骤。如果有多个具有多个类的 jar,则第一个请求会出现明显的滞后。在无服务器架构中,这种滞后可能会延迟启动时间,而启动时间是此类架构中的关键操作。应用程序类数据共享概念有助于减少应用程序的启动时间。Java 具有现有的 CDS(类数据共享)功能。通过应用程序类数据共享,Java 10 允许将应用程序类放入共享存档中。通过在多个 java 进程之间共享公共类元数据,可以减少应用程序的启动和占用空间。

过程

应用程序类数据共享过程分为 3 个步骤。

  • 创建要归档的类列表- 使用 Java Launcher 创建位于welcome.jar 中的类 Greeting.java 的welcome.lst 列表。

$java -Xshare:off -XX:+UseAppCDS -XX:DumpLoadedClassList=welcome.lst -cp welcome.jar Greeting
  • 创建 AppCDS 存档- 存档用于应用程序类数据共享的类列表。

$java -Xshare:dump -XX:+UseAppCDS -XX:SharedClassListFile=welcome.lst -XX:SharedArchiveFile=welcome.jsa -cp welcome.jar
  • 使用 AppCDS 存档- 使用 java 启动器时使用 AppCDS 存档。

$java -Xshare:on -XX:+UseAppCDS -XX:SharedArchiveFile=welcome.jsa -cp welcome.jar Greeting

Java 10 - 增强的垃圾收集

JEP 304 - 垃圾收集器接口

在 Java 10 之前,GC(垃圾收集器)实现组件分散在代码库中,并且不易替换。Java 10 引入了 Garbage-Collector 接口,以便可以插入替代的 GC 实现。它还有助于将代码库与不同的垃圾收集实现隔离。此功能是 JEP 304 的一部分。

JEP 307 - G1 的并行完整 GC

Java 9 引入了 G1(Garbage First)垃圾收集器。G1 避免了完全垃圾收集,但如果并发线程寻找收集并且内存恢复速度不够快,用户体验就会受到影响。在 Java 10 中,现在 G1 将使用回退完整垃圾收集。

通过这一更改,G1 通过并行使用 Full GC 改善了最坏情况下的延迟。目前,G1使用单线程标记-清除-压缩算法。使用 JEP 307,并行线程将启动标记-扫描-紧凑算法。可以使用以下选项控制线程数。

$java -XX:ParallelGCThreads=4

Java 10 - 区域设置增强

JEP 314 - Unicode 语言标签扩展

Java 7 引入了对BCP 47语言标签的支持。但这种 unicode 区域设置扩展仅限于日历和数字。在 Java 10 中,更新了java.util.Locale和相关类,以实现LDML 规范中指定的其他 unicode 扩展。添加了以下附加扩展。

  • cu - 货币类型

  • fw - 一周的第一天

  • rg - 区域覆盖

  • tz - 时区

以下 API 已更新。

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

Java 10 - 堆分配

JEP 316 - 替代内存设备上的堆分配

通过 Java 10 中的这一增强功能,现在用户可以指定替代内存设备,例如 NV-DIMM 到 HotSpot VM 来分配 java 堆空间。用户需要使用新选项 -XX:AllocateHeapAt 传递文件系统的路径。

-XX:AllocateHeapAt=~/etc/heap

此选项采用文件路径并进行内存映射以获得所需的结果。其他堆标志(例如 -Xmx、-Xms)继续有效。

Java 10 - 统一的 JDK 森林

JEP 296 - 将 JDK 森林合并为单一存储库

在 JDK 9 中,有八个基于模块的目录,称为 repos。

  • 科尔巴

  • 热点

  • 贾克斯普

  • 贾克斯

  • jdk

  • 语言工具

  • 纳肖恩

代码的组织方式如下:

$ROOT/jdk/src/java.base
...
$ROOT/langtools/src/java.compiler
...

从 Java 10 开始,JDK 森林被组织到单个存储库中以简化开发。现在代码组织为 -

$ROOT/src/java.base
$ROOT/src/java.compiler
...

Java 10 - 根证书

JEP 319 - 根证书

Cacerts 存储,在 Java 10 之前是一个空集。需要包含一组证书,可用于建立对供应商各种安全协议的证书链的信任。

OpenJDK 版本没有此类证书,这就是为什么 TLS 等关键安全组件在默认版本中不起作用的原因。

现在,由于 Oracle 已经使用 Oracle JAVA SE Root CA 程序开源了根证书,OpenJDK 版本现在可以拥有根证书,从而可以减少 OpenJDK 和 Oracle JDK 之间的差异。

Oracle JAVA SE Root CA 程序颁发根证书。已签署协议的供应商包含在根证书集中。未注册的供应商将包含在下一个版本中。

Java 10 - 线程本地握手

JEP 312 - 线程局部握手

在 JDK 10 中,为 JVM 引入了一个新选项-XX:ThreadLocalHandshakes。此选项仅适用于基于 x64 和 SPARC 的计算机。

此选项可用于提高 VM 性能。它允许在应用程序线程上进行回调,而无需创建全局虚拟机安全点。因此允许 JVM 停止单个线程而不停止所有线程。

由于此选项并非适用于所有平台,其他平台将回退到正常安全点。