JEP 200: The Modular JDK | 模块化 JDK
摘要
使用 Java 平台模块系统,即 JSR 376 规范和 JEP 261 实现,将 JDK 模块化。
目标
将 JDK 划分为一组模块,可以在编译时、构建时和运行时组合成各种配置,包括但不限于:
- 与完整的 Java SE 平台、完整的 JRE 和完整的 JDK 对应的配置;
- 与 Java SE 8 定义的每个 Compact Profiles 大致等同的配置;
- 只包含指定模块集合、可能由外部库和应用模块增强,并且所有这些模块都有传递依赖关系的自定义配置。
模块的定义应清楚区分标准模块(其规范受到 Java 社区流程的管辖)和特定于 JDK 的模块。它还应该区分包含在 Java SE 平台规范中、因此在每个平台实现中都是强制性的所有其他模块。
动机
Project Jigsaw 旨在为 Java SE 平台设计和实施标准的模块化系统,并将该系统应用于平台本身和 JDK。其主要目标是使平台实现更容易扩展到小型设备,提高安全性和可维护性,提高应用程序性能,并为开发人员提供更好的大规模编程工具。
描述
Design principles | 设计原则
JDK 的模块化结构实现了以下原则:
- 标准模块,其规范受到 JCP 的管辖,名称以字符串
"java."
开头。 - 所有其他模块仅属于 JDK,并且名称以字符串
"jdk."
开头。 - 如果一个模块导出包含有对其他模块中的类型引用的公共或受保护成员的包,则第一个模块必须通过
requires transitive
授予对第二个模块的隐式可读性。(这确保方法调用链的工作方式符合预期。) - 标准模块可以包含标准和非标准 API 包。如果标准模块导出标准 API 包,则导出可以带限定词;如果标准模块导出非标准 API 包,则导出必须带限定词。无论哪种情况,如果标准模块导出带限定词的包,则导出必须是 JDK 中某些模块的子集。如果标准模块是 Java SE 模块,即包含在 Java SE 平台规范中,则它不能导出任何非 SE API 包,至少在没有限定词的情况下不能导出。
- 标准模块可以依赖于一个或多个非标准模块。它不能授予任何非标准模块隐式可读性。如果它是 Java SE 模块,则不能授予任何非 SE 模块隐式可读性。
- 非标准模块不能导出任何标准 API 包。非标准模块可以对标准模块授予隐式可读性。
原则 4 和 5 的一个重要结果是,仅依赖于 Java SE 模块的代码将仅依赖于标准的 Java SE 类型,因此可移植到 Java SE 平台的所有实现。
模块图
JDK 的模块化结构可以以图形方式表示:每个模块是一个节点,如果第一个模块依赖于第二个模块,则两者之间存在一条有向边。完整的模块图节点太多,不易显示;以下是图的 传递约简 ,省略了冗余边缘(点击放大):
以下是模块图的导览:
- 标准的 Java SE 模块为橙色;非 SE 模块为蓝色。
- 如果一个模块依赖于另一个模块,并且它授予对该模块的隐式可读性,则从第一个模块到第二个模块的边缘是实线;否则,边缘是虚线。
- 最底部是
java.base
模块,其中包含诸如java.lang.Object
和java.lang.String
之类的基本类。基本模块不依赖于任何模块,而其他每个模块都依赖于基本模块。指向基本模块的边缘比其他边缘浅。 - 顶部附近是
java.se.ee
模块,它汇集了组成 Java SE 平台的所有模块,包括与 Java EE 平台规范重叠的模块。这是聚合器模块的一个例子,它收集并重新导出其他模块的内容,但不添加自己的内容。配置为包含java.se.ee
模块的运行时系统将包含 Java SE 平台的所有 API 包。如果模块是 Java SE 平台规范的一部分,那么只有当它是从java.se.ee
模块可达的标准模块时,才包含在 Java SE 平台规范中。 java.se
聚合器模块汇集了 Java SE 平台与 Java EE 不重叠的部分。- 非标准模块包括调试和可服务性工具和 API(如
jdk.jdi
、jdk.jcmd
和jdk.jconsole
)、开发工具(如jdk.compiler
、jdk.javadoc
和jdk.xml.bind
)以及各种服务提供者(如jdk.charsets
、jdk.scripting.nashorn
和jdk.crypto.ec
),通过现有的java.util.ServiceLoader
机制提供给其他模块使用。 java.smartcardio
模块是标准模块,但不属于 Java SE 平台规范的一部分,因此它的名称以字符串"java."
开头,但颜色为蓝色,并且无法从java.se
模块访问。
模块图实际上是一种新类型的 API,并且作为 API 进行指定和演化。模块图的子图根节点是 java.se.ee
模块,移除了所有非 SE 模块和相应的边缘,这在 Java SE 平台规范中进行了指定;其演化将由 JCP 管理。其余图的演化将由未来的 JEP 覆盖。在任何情况下,如果某个模块被指定为可供通用使用,则它将受到与其他 API 相同的演化约束。删除此类模块或进行不兼容的更改,特别是需要至少提前一个主要发布公示。
可以在 此处 找到所有模块的表格摘要,包括 Linux/AMD64 构建的占用空间度量。
测试
JDK 中的单元测试和回归测试以及用于运行它们的测试框架 jtreg
现在允许根据测试的模块和依赖于的模块来选择测试,以便可以测试任意配置的 JDK 模块。
此增强的主要功能测试检查配置的一组模块,以确保它是此处定义的模块的有效组合,每个模块都具有预期的内容并导出了预期的 API 包,并且模块之间具有预期的依赖关系。
JCK 现在可以测试成为 Java SE 平台规范一部分的模块图的各个方面。这包括 SE 模块的名称、其导出的 API 包以及导致 SE API 包被重新导出的它们之间的依赖关系。JCK 还可以测试 Platform Implementation 中存在的 SE 模块的任意配置。
风险和假设
此处定义的模块化结构不支持至少一个已知的用例,即希望在无需要求非常庞大的 java.desktop
模块的情况下使用 java.beans
包。它可能也无法解决其他尚未知晓的用例。如果一个关键的用例在此 JEP 的最终实现中得不到支持,我们预计可以通过重构模块图来在以后的版本中解决它。
依赖
此 JEP 是 Project Jigsaw 的几个 JEP 之一。其他 JEP 如下: