Skip to content

Latest commit

 

History

History
242 lines (146 loc) · 17.7 KB

File metadata and controls

242 lines (146 loc) · 17.7 KB

一、Java11 环境

在本章中,我们将探讨新实现的、基于时间的 Java 平台版本控制系统。我们将调查当前的 Java 环境,特别关注 Java9、Java10(18.3)和 Java11(18.9)引入的变化。我们的探索将包括对 Java9 的模块化、Javashell、外部进程控制、垃圾收集、Java 微基准线束JMH)等的概述。对于 Java10,我们将重点介绍关键的更改,包括局部变量类型推断、Java 开发工具包JDK)整合、垃圾收集、应用类数据共享CDS)、根证书等等。最后,我们将探讨 Java11 中引入的更改,包括动态类文件常量、垃圾收集、Lambdas 的局部变量类型推断等等。

本章结束时,我们将学到的内容包括:

  • 了解 Java 平台的新版本控制模型
  • 了解 Java9 的重要性
  • Java10 引入的变化带来的好处
  • Java11 引入的变化带来的好处

技术要求

本章及后续章节主要介绍 Java11,Java 平台的标准版SE)可从 Oracle 官方下载网站下载。

一个集成开发环境IDE)包就足够了。来自 JetBrains 的 IntelliJ IDEA 用于与本章和后续章节相关的所有编码。IntelliJ IDEA 的社区版可从网站下载。

了解 Java 平台的新版本控制模型

Java 的第一个版本在 1996 年作为 Java1 发布。从那时起,出现了几个增量版本,每个版本都遵循一个特性驱动的版本模型。从 Java10 开始,Oracle 实现了一个新的、基于时间的发布模型。在本节中,我们将查看原始模型,以提供一个基础来说明 Java 平台是如何演变的,并查看新版本模型及其原因。

特性驱动的发布

在 1996 年 Java1 发布之后,随后的版本的命名为 1.1、1.2、1.3 和 1.4。随着 1.5 的发布,Java 平台被称为 Java5。在 Java6 发布之前,Java5 经常更新,随后是 Java7、Java8 和 Java9

下表提供了 Java9 之前的 Java 发行历史的压缩视图:

版本名称 版本 发布年份 代号
Java1 1 1996 Oak
Java1.1 1.1 1997 (Abigail, Brutus, Chelsea)
Java2 1.2 1998 Playground
Java3 1.3 2000 Kestrel
Java4 1.4 2002 Merlin
Java5 1.5 2004 Tiger
Java6 1.6 2006 Mustang
Java7 1.7 2011 Dolphin
Java8 1.8 2014 Spider
Java9 9 2017 *不再使用代号

Java9 的发布是对 Java 平台和每个版本的编号方式的重大改变。在后 Java9 版本中,Oracle 决定放弃基于特性的模型,转而选择时间发布的模型

基于时间的发布

Java9 于 2017 年发布,2018 年计划发布两个版本。这些版本是 Java10 和 Java11。这些后 Java9 版本的版本号遵循YY.M格式。因此,随着 Java10 在 2018 年 3 月发布,版本号是 18.3。Java11 于 2018 年 9 月发布,版本号为 18.9。

新的基于时间的发布模型背后的一般前提是,发布的计划是可预测且频繁的。详情如下:

  • 专题发布:每半年(每年 3 月、9 月)发布一次
  • 更新发布:每季度发布一次
  • 长期支持发布:每三年发布一次

从开发人员的角度来看,使用此模型可以获得巨大的收益。开发人员不再需要等待 Java 平台的发布。更重要的是,没有一个版本将代表对 Java9 平台的重大改变。

了解 Java9 的重要性

毫无疑问,作为 Jigsaw 项目的一部分开发的 Java 平台的模块化是 Java9 引入 Java 平台的最大变化。最初计划用于 Java8,但推迟了,Jigsaw 项目是 Java9 最终版本推迟的主要原因之一。Jigsaw 还为 Java 平台引入了一些显著的变化,这也是 Java9 被认为是主要版本的原因之一。我们将在后面的章节中详细探讨这些特性。

除了 Jigsaw 相关的 Java 增强建议之外,还有一长串在 Java9 中实现的其他增强。本节将探讨 Java9 中引入的最重要的特性,特别是:

  • 拆解整体
  • 使用 Java Shell
  • 控制外部过程
  • 使用 G1 提高性能
  • Java 微基准线束JMH)测量性能
  • 为 HTTP 2.0 做准备
  • 包含反应式编程

拆解整体

多年来,Java 平台的工具不断发展和增加,使其成为一个巨大的整体。为了使平台更适合于嵌入式和移动设备,有必要发布精简版,如 Java 连接设备配置CDC)和 Java 微型版ME)。然而,对于 JDK 所提供的功能有不同需求的现代应用来说,这些方法并没有足够的灵活性。在这方面,对模块化系统的需求是一个至关重要的需求,不仅是为了解决 Java 工具的模块化(总的来说,HotSpot 运行时有 5000 多个 Java 类和 1500 多个 C++ 源文件,其中包含 250000 多行代码),而且还为开发人员提供了一种创建和管理的机制使用与 JDK 中使用的模块系统相同的模块化应用。Java8 提供了一种中间机制,使应用能够只使用整个 JDK 提供的 API 的一个子集,这种机制被命名为紧凑概要文件。事实上,紧凑的概要文件还为进一步的工作提供了基础,这些工作是为了打破 JDK 不同组件之间的依赖关系。为了在 Java 中实现模块系统,需要打破依赖关系。

模块系统本身以 Jigsaw 项目的名义开发,在此基础上形成了多个 Java 增强方案和一个目标 Java 规范请求JSR376)。对 JDK 代码库进行了完整的重组,同时对 JDK 可分发映像进行了完整的重组。

对于是否应该采用一个现有的成熟的 Java 模块系统(比如 OSGi)作为 JDK 的一部分,而不是提供一个全新的模块系统,社区中存在着相当大的争议。但是,OSGi 以运行时行为为目标,比如模块依赖关系的解析、模块的安装、卸载、启动和停止(在 OSGi 中也称为 bundle)、自定义模块类加载器等等

OSGi 是指 OSGi 联盟,正式名称为开放服务网关倡议。OSGi 是 Java 平台模块化系统的开放标准。

然而,Jigsaw 项目的目标是编译时模块系统,在该系统中,依赖项的解析在编译应用时发生。此外,作为 JDK 的一部分安装和卸载一个模块,就不需要在编译过程中将它显式地包含为依赖项。此外,通过类加载器的现有层次结构(引导、扩展和系统类加载器)可以加载模块类。

Java 模块系统的其他好处包括增强的安全性和性能。通过将 JDK 和应用模块化为 Jigsaw 模块,开发人员能够在组件及其相应的域之间创建定义良好的边界。这种关注点的分离与平台的安全架构保持一致,并且是更好地利用资源的一个使能器

使用 Java Shell

很长一段时间以来,Java 编程语言中一直没有标准的 Shell 来试验新的语言特性或库,或者进行快速原型设计。如果您想这样做,您可以用一个main()方法编写一个测试应用,用javac编译它,然后运行它。这既可以在命令行中完成,也可以使用 JavaIDE 完成;但是,在这两种情况下,这并不像使用交互式 Shell 那样方便。

在 JDK9 中启动交互式 Shell 非常简单,只需运行以下命令(假设 JDK9 安装的bin目录位于当前路径中):

jshell

您可能会发现,在 Java 平台的早期还没有引入交互式 Shell,这有点令人费解,因为许多编程语言(如 Python、Ruby 和其他一些语言)在其最早的版本中已经附带了交互式 Shell。然而,直到 Java9,它才出现在优先特性列表中。javaShell 使用 JShellapi,它提供了启用表达式和代码段的自动补全或求值等功能。第 6 章“Java Shell 实验”,致力于讨论 Java Shell 的细节,让开发者充分利用。

控制外部进程

在 JDK9 之前,如果要创建 Java 进程并处理进程输入/输出,必须使用以下方法之一:

  • Runtime.getRuntime.exec()方法,它允许我们在单独的操作系统进程中执行命令。使用这种方法需要您获得一个java.lang.Process实例,在该实例上提供某些操作,以便管理外部流程。
  • 新的java.lang.ProcessBuilder类,在与外部进程交互方面有更多的增强。您还需要创建一个java.lang.Process实例来表示外部进程。

这两种方法都是不灵活的,也不可移植的,因为外部进程执行的命令集高度依赖于操作系统。为了使特定的进程操作能够跨多个操作系统进行移植,还必须付出额外的努力。第 9 章“利用进程 API”开发了新的流程 API,为开发人员提供了创建和管理外部流程的知识。

使用 G1 提高性能

G1 垃圾收集器已经在 JDK7 中引入,现在在 JDK9 中默认启用。它针对具有多个处理核心和大量可用内存的系统。与以前的垃圾收集器相比,G1 有什么好处?它是如何实现这些改进的?是否需要手动调整,在什么情况下?关于 G1 的这些和其他几个问题将在第 7 章“利用默认的 G1 垃圾收集器”中讨论。

用 JMH 测量性能

在许多情况下,Java 应用可能会出现性能下降的问题,更严重的是缺乏性能测试,这些测试至少可以提供一组最低限度的性能保证来满足性能要求,而且,某些特性的性能不会随着时间的推移而下降。衡量 Java 应用的性能并非易事,特别是由于存在许多编译器和运行时优化,这些优化可能会影响性能统计。因此,为了提供更准确的性能度量,必须使用额外的度量,例如预热阶段和其他技巧。JMH 是一个框架,它包含了许多技术,以及一个方便的 API,可用于此目的。它不是一个新工具,但是包含在 Java9 的发行版中。如果您还没有将 JMH 添加到工具箱中,请阅读第 8 章、“使用 JMH 的微标记应用”,了解 JMH 在 Java 应用开发中的使用。

为 HTTP 2.0 做准备

HTTP2.0 是 HTTP1.1 协议的继承者,这个新版本的协议解决了前一个协议的一些限制和缺点。HTTP 2.0 以多种方式提高性能,并提供诸如在单个 TCP 连接中请求/响应多路复用、在服务器推送中发送响应、流控制和请求优先级等功能。Java 提供了可用于建立不安全 HTTP 1.1 连接的java.net.HttpURLConnection工具。然而,API 被认为难以维护,这一问题由于需要支持 HTTP 2.0 而变得更加复杂,因此引入了全新的客户端 API,以便通过 HTTP 2.0 或 Web 套接字协议建立连接。HTTP 2.0 客户端及其提供的功能,将在第 11 章、“新工具和工具增强”中介绍。

包含反应式编程

反应式编程是一种用于描述系统中变化传播的特定模式的范例。反应式不是 Java 本身构建的,但是可以使用第三方库(如 RxJava 或 projectreactor(Spring 框架的一部分))来建立反应式数据流。JDK9 还解决了对 API 的需求,该 API 通过为此提供java.util.concurrent.Flow类来帮助开发基于反应流思想构建的高响应性应用。Flow类以及 JDK9 中引入的其他相关更改将在第 12 章、“并发增强”中介绍。

受益于 Java10 带来的变化

Java10 于 2018 年 3 月发布,除了之前介绍的基于时间的版本控制之外,还有以下 11 个特性:

  • 局部变量类型推断
  • 将 JDK 森林整合到单个存储库中
  • 垃圾收集接口
  • G1 的并行完全垃圾收集器
  • 应用类数据共享
  • 线程本地握手
  • 删除本机头生成工具(javah
  • 其他 Unicode 语言标记扩展
  • 备用内存设备上的堆分配
  • 基于 Java 的 JIT 编译器实验
  • 根证书

本章将简要概述这些功能,随后的章节将更详细地介绍这些功能。

局部变量类型推断

从 Java10 开始,声明局部变量已经简化。开发人员不再需要包含本地变量类型的清单声明。这是使用新的var标识符完成的,如本示例所示:

var myList = new ArrayList<String>();

使用前面的代码,ArrayList<String>是推断出来的,所以我们不再需要使用ArrayList<String> myList = new ArrayList<String>();

局部变量类型推断在第 3 章、“Java11 基础”中介绍

将 JDK 森林整合到单个存储库中

在 Java10 之前,JDK 有八个存储库(CORBA、HotSpot、JDK、JAXP、JAX-WS、langtools、Nashorn 和 ROOT)。使用 Java10,这些存储库被整合到一个代码库中。值得注意的是,javafx 并不是这次整合的一部分。本课题将在第 2 章、第 11 章中进一步说明。

垃圾收集接口

Java10 带来了对垃圾收集过程的增强。新的垃圾收集器接口带来了改进,将在第 7 章“利用默认的 G1 垃圾收集器”中详细介绍。

G1 的并行完全垃圾收集器

在 Java10 中,G1 完全垃圾收集器是并行的。从 Java9 开始,G1 被设置为默认的垃圾收集器,因此这个更改具有特殊的意义。此更改将在第 7 章“利用默认的 G1 垃圾收集器”中详细说明。

应用类数据共享

类数据共享CDS)已经扩展,以支持更快的应用启动和更小的占用空间。使用 cd,开发人员可以预先解析特定的类文件并将其存储在可共享的归档文件中。我们将在第 2 章“探索 Java11”中探讨 Java 平台的这种变化。

线程本地握手

使用 Java10 及更高版本,可以停止单个线程,而不必执行全局虚拟机安全点。我们将在第 3 章“Java11 基础”中充分探讨这一变化

删除本机头生成工具(javah

为了将 Javah 工具从 JDK 中删除,进行了协调一致的工作。由于javac中提供的功能,因此此更改是有保证的。我们将在第 11 章、“新工具和工具增强”中详细说明这一变化。

附加 Unicode 语言标记扩展

Java 平台从 Java7 开始就支持语言标记。在 Java10 中,对java.util.Local和相关 API 进行了更改,以合并额外的 Unicode 语言标记。详见第 2 章、第 11 章。

备用内存设备上的堆分配

从 Java10 开始,热点虚拟机支持非 DRAM 内存设备。这将在第 3 章、“Java11 基础”中解释

基于 Java 的实验性 JIT 编译器

Java9 向我们介绍了一个基于 Java 的即时JIT)编译器。此 JIT 编译器已为 Linux/x64 平台启用。这个实验编译器将在第 14 章、“命令行标志”中进一步探讨。

根证书

从 Java10 发布开始,JDK 中就有一组默认的证书颁发机构CA)证书。这一变化及其好处将在第 3 章、“Java11 基础”中介绍

受益于 Java11 引入的变化

Java11 于 2018 年 9 月发布,具有以下四个特性:

  • 动态类文件常量
  • Epsilon 一个任意低开销的垃圾收集器
  • 删除 JavaEE 和 CORBA 模块
  • Lambda 参数的局部变量语法

本章将简要概述这些功能,随后的章节将更详细地介绍这些功能。

动态类文件常量

在 Java11 中,Java 类文件的文件格式被扩展为支持CONSTANT_Dynamic,它将创建委托给自举方法。这一变化将在第 3 章、“Java11 基础”中详细探讨

Epsilon–一个任意低开销的垃圾收集器

垃圾收集增强似乎是每个 Java 平台版本的一部分。Java11 包括一个不回收内存的被动垃圾收集器。我们将在第 7 章“利用默认的 G1 垃圾收集器”中探讨这一点。

删除 JavaEE 和 CORBA 模块

Java 企业版JavaEE)和公共对象请求代理架构CORBA)模块在 Java9 中被废弃,并从 Java11 开始从 Java 平台中移除。详见第 3 章、“Java11 基础”

Lambda 参数的局部变量语法

正如本章前面所讨论的,var标识符是在 Java10 中引入的。在最新版本 Java11 中,var可以用在隐式类型的 Lambda 表达式中。第 3 章“Java11 基础”介绍了var标识符的使用

总结

在本章中,我们探讨了新实现的、基于时间的 Java 平台版本控制系统。我们还从较高的层次了解了 Java9、10 和 11 中引入的更改(分别称为 9、18.3 和 18.9 版本)。Java9 最重要的变化是基于 Jigsaw 项目的模块化,包括关注 Javashell、控制外部进程、垃圾收集、JHM 等的其他变化。讨论了 Java10 的关键特性,包括局部变量类型推断、JDK 整合、垃圾收集、应用 CD、根证书等等。Java11 中引入的更改包括动态类文件常量、垃圾收集、Lambdas 的局部变量类型推断等等。

在下一章中,我们将研究 Java 平台中引入的几个内部更改,包括来自 Java9、10 和 11 的更改。

问题

  1. 2019 年第一个 Java 版本会是什么?
  2. 新的 Java 基于时间的发布模型的主要优点是什么? 
  3. JDK9 对 Java 平台最重要的改变是什么?
  4. Java11 删除了什么:CORBA、Lambda 还是 G1?
  5. CD 支持更快的启动还是更高效的垃圾收集?
  6. 什么是 Epsilon?
  7. var是数据类型、标识符、保留字还是关键字?
  8. 哪个 Java 版本向 Java 平台引入了根证书?
  9. 哪个版本包括对垃圾收集的增强?
  10. Java 中默认的垃圾收集器是什么?

进一步阅读

本调查章节对 Java 平台的最新变化进行了粗略的介绍。如果您不熟悉其中任何一个概念,请考虑使用以下一个或多个资源来复习 Java 知识: