代码之家  ›  专栏  ›  技术社区  ›  ZhekaKozlov

什么是自动模块?

  •  48
  • ZhekaKozlov  · 技术社区  · 7 年前

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

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

    3 回复  |  直到 7 年前
        1
  •  60
  •   Nicolai Parlog    6 年前

    我首先回答你的实际问题(“什么是自动模块?”),但我也解释了它们是什么 对于

    the module's properties (name, requires, exports) . 对于普通JAR(没有模块描述符),这种方法不起作用,那么模块系统应该做什么呢?它会自动创建一个模块-一个 automatic module 可以说,对这三种属性进行了最安全的猜测。

    名称

    获得名称需要两个步骤:

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

    Maven warns about that.

    要求

    由于普通JAR表示no requires子句,因此模块系统允许自动模块将所有其他模块读入 readability graph (又称模块图)。与显式模块不同,自动模块还读取未命名模块,该模块包含从类路径加载的所有内容。这个看似微不足道的细节非常重要(见下文)。

    尽管如此,自动模块还有一些可读性要求:

    • 一旦第一个自动模块被解决,所有其他模块也都被解决了。这意味着,一旦模块路径上的单个普通JAR被另一个模块引用,所有普通JAR都将作为自动模块加载。
    • 自动模块 imply readability 在所有其他自动模块上,这意味着一个模块读取其中一个模块,就会读取所有模块。

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

    导出/打开

    更多

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

    Main-Class 清单条目也会被处理,因此定义清单条目的普通JAR可以像自动模块一样启动,在自动模块中,主类用 jar 工具(即。 java --module-path my-app.jar --module my.app ).

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

    什么是自动模块 ?

    requires 条款。

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

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

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

        2
  •  9
  •   Naman    7 年前

    automatic module 是隐式定义的命名模块, 从那以后 没有模块声明 相反,是显式定义的,带有模块声明;我们将 以下简称为 显式模块 .

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

    自动模块名称 在其主清单条目中。否则,模块名由 ModuleFinder


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

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

    .. 没有切实可行的方法来区分 自动模块用于其他模块,或 类仍在类路径上。 自动模块中的每个包 因此,即使它实际上可能是

    ... 没有切实可行的方法提前判断哪些其他模块 自动模块可能取决于。解析模块图后, 因此 制作了一个自动模块,用于每隔一个指定的

    其中一个 proposals -自动模块提供了传统的封装级别: 所有软件包都是 开放式深层反光通道 导出用于普通编译时和运行时访问 它们的公共类型 .


    此外,一个自动模块

    赠款

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

        3
  •  5
  •   M A    3 年前

    (关于缺少完整定义,您似乎是对的,因为我在语言或JVM规范中没有找到它)

    Javadocs在 java.lang.module 包类。

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

    没有 module-info.class 在其顶级目录中定义了一个 自动模块 ,如下所示:

    • 如果JAR文件具有属性“ Automatic-Module-Name

    ...

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

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

    编辑(2021年):

    section on module dependences Java语言规范中有以下有趣的注释:

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

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