当前位置: 首页 > 知识库问答 >
问题:

什么是自动模块?

夏华藏
2023-03-14

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

那么,什么是自动模块?它出口所有的包裹吗?它能打开所有的包裹吗?它是否读取所有其他模块?

共有3个答案

顾骏祥
2023-03-14

(你似乎是对的,因为我在语言或JVM规范中没有找到完整的定义)

Javadocs提供了大量的形式化定义,尽管是在java.lang.module包类中。

部分引用自https://docs.oracle.com/javase/9/docs/api/java/lang/module/ModuleFinder.html#automatic-模块:

在顶层目录中没有module-info.class的JAR文件定义了一个自动模块,如下所示:

  • 如果JAR文件在其主清单中具有属性自动模块名称,则其值为模块名称。模块名称是从JAR文件的名称派生而来的。

...

来自https://docs.oracle.com/javase/9/docs/api/java/lang/module/ModuleDescriptor.html:

自动模块的模块描述符不声明任何依赖项(对java.base的强制依赖项除外),也不声明任何导出或打开的包。自动模块在解析期间接受特殊处理,以便读取配置中的所有其他模块。当在Java虚拟机中实例化一个自动模块时,它会读取每个未命名的模块,并被视为所有包都已导出并打开。

编辑(2021):

关于Java语言规范中模块依赖关系的本节有以下有趣的注释:

JavaSE平台区分显式声明的命名模块(即使用模块声明)和隐式声明的命名模块(即自动模块)。然而,Java编程语言并没有表现出这种区别:requires指令引用命名模块,而不考虑它们是显式声明的还是隐式声明的。

虽然自动模块便于迁移,但它们是不可靠的,因为当它们的作者将它们转换为显式声明的模块时,它们的名称和导出的包可能会更改。如果要求指令引用自动模块,则鼓励Java编译器发出警告。如果指令中出现传递修饰符,建议使用特别强的警告。

郎正平
2023-03-14

自动模块是隐式定义的命名模块,因为它没有模块声明。相比之下,普通命名模块是显式定义的,带有模块声明;此后,我们将这些模块称为显式模块。

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

如果工件的主清单条目中有属性automatic module name,则自动模块的模块名从用于包含工件的JAR文件派生。模块名由ModuleFinder从JAR文件名派生而来。

由于自动模块没有模块声明这一事实,实际上不可能判断它读取、打开或导出的所有模块或包。

➜ 因此,由于没有针对驻留在自动模块中的包的显式导出/打开,如下所述-

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

进一步引用链接-

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

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

➜ 另外,一个自动模块

授予所有其他自动模块隐含可读性

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

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

颜楚青
2023-03-14

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

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

获取名称的过程分为两步:

  • 如果JAR在其清单中定义了自动模块名头,它将定义模块名

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

由于一个普通的JAR表达了不需要子句,模块系统允许自动模块读取所有其他模块,使其进入可读性图(又名模块图)。与显式模块不同,自动模块还读取未命名模块,该模块包含从类路径加载的所有内容。这个看似微不足道的细节,原来非常重要(见下文)。

自动模块还有一些可读性方面的问题,不过:

  • 一旦第一个自动模块被解决,所有其他模块也将被解决。这意味着,一旦模块路径上的一个普通JAR被另一个模块引用,所有普通JAR都将作为自动模块加载。

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

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

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

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

一旦自动模块被创建,它将被视为任何其他模块。这明确地包括该模块系统检查它的任何其他模块,例如用于拆分包。

引入模块的原因之一是为了使编译和启动应用程序更加可靠,并且能够更快地发现错误,这在类路径中是可能的。其中一个关键方面是需要子句。

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

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

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

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

 类似资料:
  • 问题内容: 在stackoverflow上多次提到自动模块,但是我找不到自动模块的完整,简洁和自足的定义。 那么,什么是自动模块?是否导出所有软件包?是否打开所有包装?它会读取所有其他模块吗? 问题答案: 我首先回答您的实际问题(“什么是自动模块?”),但我还要解释它们的 用途 。很难理解为什么自动模块在没有这些信息的情况下会表现出自己的方式。 模块系统根据在模块路径上找到的每个JAR创建一个模块

  • 本文向大家介绍什么是驱动模块?相关面试题,主要包含被问及什么是驱动模块?时的应答技巧和注意事项,需要的朋友参考一下 驱动模块大多数称为是“主程序”,它接受测试数据并将数据传递到被测试模块,单元测试一个函数单元时,被测单元本身是不能独立运行的,需要为其传送数据,为此写驱动。 驱动模块主要完成以下内容: 1.接受测试输入 2.对输入进行判断 3.将输入传递给被测试单元,驱动被测单元执行 4.接受被测单

  • AC自动机,我知道很多人看到这个会十分好奇,不过这个自动机它又叫做 Automaton。我相信大家在初学自动机相关内容时,许多人难以建立对自动机的初步印象,尤其是在自学的时侯。让我们切入正题,通过这段时间对自动机的研究,然后制作若干的gif,已经可以呈现出一个相对直观的自动机形态,我们先对基础的知识有个了解。 定义:AC自动机是以Trie的结构为基础,结合KMP的思想建立的。 什么是AC自动机?

  • 本文向大家介绍什么是分层自动化?相关面试题,主要包含被问及什么是分层自动化?时的应答技巧和注意事项,需要的朋友参考一下 金字塔结构, 最底层UnitTest,往上接口API/集成起来的service, 最上面UI自动化

  • Python 提供了强大的 模块支持,主要体现在,不仅 Python 标准库中包含了大量的模块(称为标准模块),还有大量的第三方模块,开发者自己也可以开发自定义模块。通过这些强大的模块可以极大地提高开发者的开发效率。 那么,模块到底指的是什么呢?模块,英文为 Modules,至于模块到底是什么,可以用一句话总结: 模块就是 Python  程序。换句话说,任何 Python 程序都可以作为模块,包

  • 本文向大家介绍什么是Perl模块?,包括了什么是Perl模块?的使用技巧和注意事项,需要的朋友参考一下 Perl模块是在库文件中定义的可重用软件包,该文件的名称与扩展名为.pm的软件包的名称相同。 一个名为Foo.pm的Perl模块文件可能包含这样的语句。 关于Perl模块的几点要点 需要和 使用的功能 将加载模块。 两者都使用@INC中的搜索路径列表来查找模块。 这两个函数 都需要并 使用调用