什么是自动模块?什么是自动模块?什么是自动模块?

自动模块在stackoverflow上多次被提及,但我找不到一个完整,简洁和自给自足的自动模块定义。

那么,什么是自动模块呢?它是否导出所有包?它会打开所有软件包吗?它是否读取所有其他模块?


答案 1

我首先回答你的实际问题(“什么是自动模块?”),但我也解释了它们的作用。很难理解为什么自动模块在没有这些信息的情况下会以这种方式运行。

什么是自动模块?

模块系统从它在模块路径上找到的每个 JAR 创建一个模块。对于模块化 JAR(即带有模块描述符的 JAR),这很简单,因为它们定义了模块的属性(名称、要求、导出)。对于普通的 JAR(没有模块描述符),这种方法不起作用,那么模块系统应该做什么呢?它会自动创建一个模块 - 可以说是一个自动模块 - 并对三个属性进行最安全的猜测。

名字

派生名称的过程分为两个步骤:

  • 如果 JAR 在其清单中定义了标头,则定义模块的名称Automatic-Module-Name
  • 否则,将使用 JAR 文件名来确定名称

第二种方法本质上是不稳定的,因此不应发布依赖于此类自动模块的模块。Maven对此发出了警告。

需要

由于普通的 JAR 表示无必需子句,因此模块系统允许自动模块读取所有其他进入可读性图的模块(也称为模块图)。与显式模块不同,自动模块也读取未命名模块,该模块包含从类路径加载的所有内容。这个看似微不足道的细节被证明是非常重要的(见下文)。

不过,自动模块有一些进一步的可读性怪癖:

  • 一旦第一个自动模块得到解决,所有其他模块也是如此。这意味着一旦模块路径上的单个普通 JAR 被另一个模块引用,所有普通 JAR 都将作为自动模块加载。
  • 自动模块意味着所有其他自动模块的可读性,这意味着读取其中一个模块的模块读取所有自动模块。

总而言之,这可能会产生一个不幸的效果,即依赖于多个普通JAR的显式模块(即非自动模块)只需要其中一个(只要其他模块也最终在模块路径上)。

导出/打开

由于 JAR 不包含哪些包被视为公共 API 以及哪些不是公共 API 的信息,因此模块系统会导出所有包,并打开它们进行深度反射。

更多

模块系统还扫描并使自动模块提供其中命名的服务。假定自动模块允许使用所有服务。META-INF/services

最后,还会处理清单条目,因此可以像使用工具设置主类的自动模块一样启动定义清单条目的普通JAR(即)。Main-Classjarjava --module-path my-app.jar --module my.app

适当的模块

创建自动模块后,它将被视为任何其他模块。这明确包括模块系统将其检查为任何其他模块,例如拆分包。

什么是自动模块?

引入模块的原因之一是使编译和启动应用程序更加可靠,并更快地发现错误,而类路径可能。其中的一个关键方面是条款。requires

为了保持它们的可靠性,模块声明不能要求除命名模块以外的任何内容,这排除了从类路径加载的所有内容。如果故事到此结束,模块化JAR只能依赖于其他模块化JAR,这将迫使生态系统自下而上地进行模块化。

然而,这是不可接受的,因此引入了自动模块作为模块化JAR依赖于非模块化JAR的一种手段,而您需要做的就是将普通JAR放在模块路径上,并按照模块系统给出的名称要求它。

有趣的是,由于自动模块读取未命名的模块,因此将其依赖项保留在类路径上是可行的(我通常建议这样做)。这样,自动模块充当从模块到类路径的桥梁。

您的模块可以位于一侧,需要其直接依赖项作为自动模块,而间接依赖项可以保留在另一侧。每当您的一个依赖项变成显式模块时,它就会将桥留在模块化端,并将其直接依赖项作为自动模块绘制到桥上。


答案 2

自动模块是隐式定义的命名模块,因为它没有模块声明。相比之下,一个普通的命名模块是用模块声明显式定义的;从此以后,我们将把它们称为显式模块

使用这些项目的主要好处是,它们允许您在编译或运行时将工件视为模块,而无需等待将其迁移到模块化结构。

自动模块的模块名称派生自用于包含工件的 JAR 文件(如果其主清单条目中具有属性 Automatic-Module-Name)。模块名称由模块查找器从 JAR 文件的名称派生而来。


由于自动模块没有模块声明,因此实际上无法判断它读取,打开或导出的所有模块或包。

➜ 因此,由于自动模块中没有显式导出/打开包,因此描述为 -

..没有实用的方法来判断自动模块中的哪些包是供其他模块使用的,或者由仍在类路径上的类使用的。因此,自动模块中的每个包都被视为已导出,即使它实际上可能仅供内部使用。

➜ 进一步引用链接 -

...没有实用的方法来提前判断自动模块可能依赖于哪些其他模块。因此,在解析模块图后,将创建一个自动模块来读取其他每个命名模块,无论是自动的还是显式的。

其中一个建议 - 自动模块提供了传统的封装级别:所有包都是开放的,以进行深度反射访问并导出用于普通编译时和运行时访问其公共类型


➜ 此外,自动模块

所有其他自动模块提供隐含的可读性

由于这个原因,在模块中使用多个自动模块时,其

..无法确定自动模块 (x.y.z) 中的某个导出包是否包含其签名引用在某个其他自动模块 (a.b.c) 中定义的类型的类型。


推荐