JEP 200:模块化 JDK
概括
使用由JSR 376指定并由JEP 261实现的Java 平台模块系统来模块化 JDK。
目标
将 JDK 划分为一组模块,这些模块可以在编译时、构建时和运行时组合成各种配置,包括但不限于:
-
与完整的 Java SE 平台、完整的 JRE 和完整的 JDK 相对应的配置;
-
配置在内容上大致相当于Java SE 8中定义的每个紧凑配置文件;和
-
自定义配置仅包含一组可能由外部库和应用程序模块增强的指定模块,以及所有这些模块传递所需的模块。
模块化结构的定义应该明确区分标准模块(其规范由Java Community Process管理)和特定于 JDK 的模块。它还应该将 Java SE 平台规范中包含的模块与所有其他模块区分开来,从而在每个平台实现中强制执行。
动机
Jigsaw 项目旨在为 Java SE 平台设计和实现一个标准模块系统,并将该系统应用于平台本身和 JDK。其主要目标是使平台的实现更容易扩展到小型设备,提高安全性和可维护性,提高应用程序性能,并为开发人员提供更好的大型编程工具。
描述
设计原则
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.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](http://docs.oracle.com/javase/8/docs/api/java/util/ServiceLoader.html)
-
该
java.smartcardio
模块是标准模块,但不是 Java SE 平台规范的一部分,因此其名称以字符串开头"java."
,但颜色为蓝色,并且无法从java.se
模块访问。
实际上,模块图是一种新型 API,并且是这样指定和发展的。 Java SE 平台规范中指定了以模块为根的模块图的子图java.se.ee
,删除了所有非 SE 模块和相应的边;其演变将受 JCP 管辖。未来的 JEP 将涵盖该图其余部分的演变。在任何一种情况下,如果一个模块被指定为可用于一般用途,那么它将受到与其他 API 相同的进化约束。特别是,删除此类模块或以不兼容的方式对其进行更改将需要提前至少发布一个主要版本进行公告。
此处提供了所有模块的表格摘要,包括 Linux/AMD64 构建的占用空间指标。
测试
JDK 中的单元测试和回归测试以及[jtreg](http://openjdk.java.net/jtreg/)
用于运行它们的工具现在允许根据它们测试的模块和它们所依赖的模块来选择测试,以便可以测试 JDK 模块的任意配置。
此增强功能的主要功能测试检查一组已配置的模块,以确保它是此处定义的模块的有效组合,每个模块具有预期的内容并导出预期的 API 包,并且模块具有预期的依赖关系。
JCK 现在可以测试模块图的那些方面,这些方面已成为 Java SE 平台规范的一部分。这包括 SE 模块的名称、它们导出的 API 包以及它们之间导致 SE API 包重新导出的依赖关系。 JCK 还可以测试平台实现中存在的 SE 模块的任意配置。
风险和假设
这里定义的模块化结构不支持至少一种已知的用例,即想要使用包java.beans
而不需要非常大的java.desktop
模块的用例。它可能无法解决目前未知的其他用例。如果此 JEP 的最终实现不支持关键用例,那么我们希望能够通过重构模块图在以后的版本中解决它。
依赖关系
该 JEP 是Project Jigsaw的几个 JEP 之一。其他 JEP 是: