在stackoverflow上多次提到自动模块,但我找不到自动模块的完整,简洁和自给自足的定义。
那么,什么是自动模块?它是否导出所有包裹?它打开所有包裹吗?它是否读取所有其他模块?
答案 0 :(得分:25)
我首先回答你的实际问题("什么是自动模块?"),但我也解释了的 。很难理解为什么自动模块在没有这些信息的情况下表现得如此。
模块系统从它在模块路径上找到的每个JAR创建一个模块。对于模块化JAR(即具有模块描述符的JAR),它们定义the module's properties (name, requires, exports)时很简单。对于普通的JAR(没有模块描述符),这种方法不起作用,那么模块系统应该做什么呢?它会自动创建一个模块 - automatic module,可以这么说 - 并对三个属性进行最安全的猜测。
获取名称分为两步:
Automatic-Module-Name
标头,则它定义了模块的名称第二种方法本质上是不稳定的,因此不应发布依赖于这种自动模块的模块。 Maven warns about that.
由于普通JAR表示没有require子句,因此模块系统允许自动模块读取所有其他模块,使其成为readability graph(又称模块图)。与显式模块不同,自动模块也读取未命名的模块,该模块包含从类路径加载的所有内容。这个看似微不足道的细节非常重要(见下文)。
自动模块有一些进一步的可读性怪癖,但是:
由于JAR不包含哪些包被视为公共API而且不包含任何信息,因此模块系统会导出所有包并打开它们以进行深度反射。
模块系统还扫描META-INF/services
并使自动模块提供其中指定的服务。假设允许自动模块使用所有服务。
最后,还会处理Main-Class
清单条目,因此可以像使用jar
工具设置主类的自动模块一样启动定义一个的普通JAR(即{ {1}})。
创建自动模块后,它将被视为任何其他模块。这明确地包括模块系统将其检查为任何其他模块,例如对于拆分包。
引入模块的原因之一是使编译和启动应用程序更加可靠,并且可以更快地发现类路径可能出现的错误。其中一个关键方面是java --module-path my-app.jar --module my.app
条款。
为了保证它们的可靠性,模块声明无法获得除命名模块之外的任何其他内容,这会排除从类路径加载的所有内容。如果故事在这里结束,模块化JAR只能依赖于其他模块化JAR,这将迫使生态系统从下往上进行模块化。
这是不可接受的,因此引入了自动模块作为模块化JAR依赖非模块化JAR的手段,您需要做的就是将普通JAR放在模块路径上并通过名称来命令它模块系统给出了它。
有趣的是,因为自动模块读取未命名的模块,所以可行(我通常建议这样做)将其依赖项留在类路径上。这样,自动模块就可以充当从模块到类路径的桥梁。
您的模块可以位于一侧,需要它们作为自动模块的直接依赖关系,并且间接依赖关系可以保留在另一侧。 每当您的一个依赖项变成一个显式模块时,它就会在模块化的一侧留下桥接器,并将其直接依赖关系作为自动模块绘制到桥上。
答案 1 :(得分:2)
automatic module 是一个隐式定义的命名模块, 因为它没有模块声明。一个普通的命名模块, 相比之下,使用模块声明明确定义;我们会 从此以后将它们称为显式模块。
使用它们的主要好处是它们允许您在编译或运行时将工件视为模块,而无需等待它迁移到模块化结构。
自动模块的模块名称是从用于包含工件的JAR文件派生的,如果它在主清单条目中具有属性自动模块名称。否则,模块名称将由ModuleFinder
的JAR文件名称派生。
由于自动模块没有模块声明这一事实导致所有模块或包读取,打开或导出的内容实际上是不可行的。
➜因此,对于驻留在自动模块中的软件包没有明确的导出/打开,描述为 -
..没有实用的方法来分辨哪个包 自动模块旨在供其他模块使用,或者由其他模块使用 类仍然在类路径上。 自动模块中的每个包 因此,即使它实际上是,也被认为是出口的 仅供内部使用。
➜进一步引用链接 -
...没有实际的方法可以事先告诉其他哪些模块 自动模块可能依赖于。解决模块图后, 因此,使自动模块读取所有其他命名 模块,无论是自动还是显式。
proposals中的一个 - 自动模块提供传统的封装级别:所有包都是打开以进行深层反射访问和导出以进行普通编译 - 时间和运行时访问到他们的公共类型。
➜另外,还有一个自动模块
向所有其他自动模块授予隐含的可读性
由于这个原因,在模块中使用多个自动模块时
..无法确定是否可以导出其中一个 自动模块(x.y.z)中的包包含其签名的类型 是指在某些其他自动模块(a.b.c)中定义的类型。
答案 2 :(得分:1)
(你似乎对缺少完整的定义似乎是正确的,因为我没有在语言或JVM规范中找到它)
Javadocs在module-info.class
包类中提供了大量的正式定义。
https://docs.oracle.com/javase/9/docs/api/java/lang/module/ModuleFinder.html#automatic-modules的部分引用:
在其顶级目录中没有
Automatic-Module-Name
的JAR文件定义了自动模块,如下所示:
- 如果JAR文件具有属性"
java.base
"在其主要清单中,它的值是模块名称。否则,模块名称将从JAR文件的名称派生。...
来自https://docs.oracle.com/javase/9/docs/api/java/lang/module/ModuleDescriptor.html:
自动模块的模块描述符不声明任何依赖(除了对{{1}}的强制依赖),并且不声明任何导出或打开的包。自动模块在分辨率期间接受特殊处理,以便它们读取配置中的所有其他模块。当在Java虚拟机中实例化自动模块时,它会读取每个未命名的模块,并被视为所有包都被导出和打开。