module-info.java 放在哪个目录?

In which directory does module-info.java go?

从项目 Jigsaw 的快速入门教程来看,module-info.java 似乎进入了一个带有模块名称的目录,例如,对于模块 my.module包含一个 class MyClass:

bin/
    my.module/
        module-info.class
        my/
            module/
                MyClass.class

然后,仍然按照教程,在调用 MyClass 时(假设它有一个 method),模块路径选项被赋予 bin 目录:

java -p path/to/bin -m my.module/my.module.MyClass

到目前为止,还不错。

然而,如果我写:

java -p path/to/bin/my.module -m my.module/my.module.MyClass

而且我不明白为什么两者都有效。

如果 bin 包含两个模块没有区别:如果两个目录都在模块路径中,第二个版本仍然有效(如果只有 bin 在模块路径中,它也有效,如教程中所述)。


现在,当我尝试使用 Eclipse 创建 Maven 项目时,使用 Java 9 个模块,module-info.java 驻留在 src/man/java 目录中,同样,module-info.class 在 target/classes 中。所以现在包含 module-info.class 文件的目录与模块名称无关。

并且 target/classes 也在模块路径中(当我检查构建配置时)。这与上面的第二种情况类似,java -p path/to/bin/my.module -m my.module/my.module.MyClass。 所以,显然,Java只使用module-info.class的内容来发现模块名,而目录名是任意的?

但是,在第一种情况下,当我写 java -p path/to/bin -m my.module/my.module.MyClass 时,这意味着 Java 将在模块路径中的目录中查找目录。

我觉得我错过了一些重要的东西。 Java在模块路径的目录中查找模块的方式有明确的解释吗?什么真正指定了一个模块? (我的印象是:不是目录,只有模块-info.java)。


让我更加困惑的是:Oracle documentation 指出:

--module-path modulepath... or -p modulepath

A semicolon (;) separated list of directories in which each directory is a directory of modules.

但这显然不是故事的全部,至少 Eclipse 不是如何使用此选项的。


注意:我看过 ,但它并没有真正帮助:一个答案说模块-info.java 进入 src/java/,另一个说它进入一个目录其名称是模块名称。显然两者都是正确的,但他们没有解释为什么,并且存在明显的矛盾。

来自 java.lang.module.ModuleFinder#of(Path...) 的文档:

Returns a module finder that locates modules on the file system by searching a sequence of directories and/or packaged modules. Each element in the given array is one of:

  1. A path to a directory of modules.
  2. A path to the top-level directory of an exploded module.
  3. A path to a packaged module.

The module finder locates modules by searching each directory, exploded module, or packaged module in array index order. It finds the first occurrence of a module with a given name and ignores other modules of that name that appear later in the sequence.

If an element is a path to a directory of modules then each entry in the directory is a packaged module or the top-level directory of an exploded module [emphasis added]. It is an error if a directory contains more than one module with the same name. If an element is a path to a directory, and that directory contains a file named module-info.class, then the directory is treated as an exploded module rather than a directory of modules [emphasis added].

The module finder returned by this method supports modules packaged as JAR files. A JAR file with a module-info.class in its top-level directory, or in a versioned entry in a multi-release JAR file, is a modular JAR file and thus defines an explicit module. [...]

[...]

  • 当您使用 --module-path path/to/bin 时,路径条目被视为 模块目录 。这是因为 bin 目录(即顶级目录)中没有 module-info.class 文件。

    • 据我所知,模块目录中的任何分解模块都不需要有一个top-名称与模块名称匹配的级别目录。这只是一个约定。换句话说,您可以将 my.module 目录重命名为您想要的任何名称; ModuleFinder 只是查看目录以查看是否存在 module-info.class 文件。
  • 当您使用 --module-path path/to/bin/my.module 时,路径条目被视为 分解模块 。这是因为 my.module 目录(即顶级目录)中存在 module-info.class 文件。

    • 使用Maven等构建工具时也是如此。 target/classes 目录是一个 分解模块 因为 module-info.class 文件存在于顶级目录中。

不幸的是,我找不到任何说明上述 ModuleFinder 实现在执行 java 时保证在内部使用的内容。但是,很可能使用的是上面的内容。