Module  java.base

Package java.lang.module

通过分辨率和服务绑定来支持模块描述符和创建模块配置的类。

除非另有说明,否则将null参数传递给此程序包中任何类或接口的构造函数或方法将导致抛出NullPointerException 另外,除非另有说明,否则调用包含null元素的数组或集合的方法将导致一个NullPointerException

Resolution

分辨率是计算模块如何相互依赖的过程。 该过程发生在编译时和运行时。

分辨率是一个两步的过程。 第一步递归地枚举一组根模块的“require”指令。 如果所有枚举的模块都是可观察的,则第二步计算其可读性图。 可读性图表示了模块如何相互依赖,从而控制跨模块边界的访问。

步骤1:递归枚举

递归枚举采用一组模块名称,查找每个模块声明,对于每个模块声明,递归枚举:

  • 'require'指令与'传递'修饰符给出的模块名称,以及

  • 在主机系统的判断下,由“require”指令给出的模块名称没有“传递”修饰符。

模块声明在一组可观察模块中查找。 可视化模块的集合以实现特定的方式确定。 可观察模块的集合可以包括具有明确声明的模块(即,具有module-info.java源文件或module-info.class文件)和具有隐式声明的模块(即automatic modules )。 因为一个自动模块没有明确的模块声明,所以它没有自己的'require'指令,尽管它的名字可以由显式模块声明的'requires'指令给出。

根据模块的名称作为该算法的初始输入,根据实现特定的方式确定。 该组模块可以包括自动模块。

如果至少有一个自动模块被这个算法枚举,那么每个可观察的自动模块都必须被枚举,无论他们的名字是否由显式模块声明的'require'指令给出。

如果发生以下任何一种情况,则解决方法失败:

  • 任何根模块都不可观察。

  • 名称由“要求”指令与“传递”修饰符赋予的任何模块都不可观察。

  • 由主机系统决定,任何名称由“require”指令而不带“传递”修饰符的模块都不可观察。

  • 此步骤中的算法枚举了相同的模块名称两次。 这表示'require'指令中的一个循环,忽略任何'传递'修饰符。

否则,决议进入步骤2。

步骤2:计算可读性图

'require'指令(不管'传递')表示一个模块依赖于其他模块。 “传递”修饰符的作用是使附加模块也依赖于其他模块。 如果模块M'需要传递性N',那么M不仅取决于N,而且取决于M的任何模块也取决于N。这允许M被重构,使得其内容的一些或全部可以被移动到新的模块N不会破坏具有'require M'指令的模块。

模块依赖性由可读性图表示。 可读性图是一个有向图,其顶点是在步骤1中列举的模块,其边缘表示模块对之间的可读性。 边缘的规定如下:

首先,可读性由枚举模块的“require”指令决定,忽略任何“传递”修饰符:

  • 对于每个需要“B:A”的枚举模块A,读取“B.

  • 对于自动的每个枚举模块X:X“读取”每隔一个枚举的模块(这就像“自动模块对每个其他枚举模块都有”require“指令)一样。

第二,可读性被增加以考虑“传递性”修饰符:

  • 对于每个列举的模块A,“读取”B:

    • 如果B'需要传递'C',那么A“读取”C“以及”B“。这个扩展是递归的:因为A”读取“C”,如果C'需要传递'D',那么A“读取”D“以及”C“ B.

    • 如果B是自动模块,则A“读取”每隔一个枚举的自动模块。 (“仿佛”自动模块对每个其他枚举的自动模块都有“需要传递”指令)。

最后,每个模块“读”本身。

如果可读性图中出现以下任何一种情况,则解析失败:

  • 模块“读取”两个或多个具有相同名称的模块。 这包括模块“读”另一个与其自身名称相同的情况。

  • 两个或多个模块将具有相同名称的包导出到“读取”两者的模块。 这包括包含包p的模块M“读取”将p导出到M的另一个模块的情况。

  • 模块M声明它使用pS'或'提供pS与...',但是包p不是模块M,也不会由M“读取”的任何模块导出到M。

否则,分辨率成功,解析结果是可读性图。

根模块

编译时根组件通常是正在编译的一组模块。 在运行时,根组件通常是指定给“java”启动器的应用程序模块。 当在未命名的模块中编译代码时,或者在从类路径加载主应用程序类时的运行时,默认的根模块是实现特定的(在JDK实现中它是模块“java.se”,如果可观察,以及导出API的每个可观察模块)。

可观察模块

编译时和运行时的可观察模块可以通过搜索几个不同的路径,也可以通过搜索内置到环境中的编译模块来确定。 搜索顺序如下:

  1. 在编译时只有编译模块的路径。 此路径包含源代码形式的模块定义。

  2. 升级模块路径。 该路径包含模块的编译定义,优先于(3)和(4)中存在的任何可升级模块的编译定义。 请参阅Java SE平台,指定哪些标准模块可升级。

  3. 系统模块是内置于环境中的编译定义。

  4. 应用程序模块路径。 此路径包含库和应用程序模块的编译定义。

'require'指令与'static'修饰符

'require'指令具有'static'修饰符在运行时表达可选依赖。 如果模块声明它需要静态M',那么分辨率不会搜索可观察模块M以满足依赖性。 然而,如果在步骤1中递归地枚举M,那么枚举的所有模块和“需要静态M”将读取M.

完整性

解决方案在编译时可能是部分的,因为完整的传递闭包可能不需要编译一组模块。 最小程度上,在编译时构建和验证的可读性图包括正在编译的模块,它们的直接依赖关系以及所有隐式声明的依赖性(需要传递)。

在运行时,分辨率是一个加法过程。 步骤1中的递归枚举可能与先前的分辨率相关,因此当由以前(或父级)分辨率枚举时,不会枚举根模块或“require”指令中命名的模块。 因此,作为分辨率结果的可读性图可以具有在步骤1中枚举的模块的顶点,但是具有表示模块读取由先前(或父级)分辨率枚举的模块的边缘。

从以下版本开始:
9