java - module-info.java 在哪个目录下?
问题描述
从项目Jigsaw的快速入门教程中,似乎 module-info.java 进入了具有模块名称的目录,例如,对于包含类 MyClass 的模块 my.module:
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
在模块路径中,它也有效,如教程中所述)。
现在,当我尝试使用 Java 9 模块使用 Eclipse 创建 Maven 项目时,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 在模块路径中的目录中查找模块的方式是否有明确的解释?什么真正指定了一个模块?(我的印象是:不是目录,只有module-info.java)。
让我更加困惑的是:Oracle 文档指出:
--module-path 模块路径... 或 -p 模块路径
分号 (;) 分隔的目录列表,其中每个目录都是模块目录。
但显然这不是全部,至少不是 Eclipse 使用此选项的方式。
注意:我见过这个问题,但它并没有真正帮助:一个答案说 module-info.java 进入 src/java/,另一个说它进入一个名为模块名称的目录。显然两者都是正确的,但他们没有解释原因,并且存在明显的矛盾。
解决方案
从以下文档java.lang.module.ModuleFinder#of(Path...)
:
返回一个模块查找器,它通过搜索一系列目录和/或打包模块来定位文件系统上的模块。给定数组中的每个元素都是以下之一:
- 模块目录的路径。
- 展开模块的顶级目录的路径。
- 打包模块的路径。
模块查找器通过按数组索引顺序搜索每个目录、展开的模块或打包的模块来定位模块。它找到具有给定名称的模块的第一次出现,并忽略序列中稍后出现的具有该名称的其他模块。
如果元素是模块目录的路径,则目录中的每个条目都是打包的模块或分解模块的顶级目录[强调添加]。如果一个目录包含多个具有相同名称的模块,则会发生错误。如果一个元素是一个目录的路径,并且该目录包含一个名为 的文件
module-info.class
,则该目录将被视为展开的模块,而不是模块的目录[强调添加]。此方法返回的模块查找器支持打包为 JAR 文件的模块。
module-info.class
在其顶级目录中或在多版本JAR文件的版本化条目中具有 的JAR 文件是模块化 JAR 文件,因此定义了显式模块。[...][...]
当您使用
--module-path path/to/bin
路径条目时,将被视为模块的目录。这是因为目录(即顶级目录)中没有module-info.class
文件。bin
- 据我所知,模块目录中的任何展开的模块都不需要具有名称与模块名称匹配的顶级目录。这只是一个约定。换句话说,您可以将
my.module
目录重命名为您想要的任何名称;ModuleFinder
只需查看目录以查看是否存在文件module-info.class
。
- 据我所知,模块目录中的任何展开的模块都不需要具有名称与模块名称匹配的顶级目录。这只是一个约定。换句话说,您可以将
当您使用
--module-path path/to/bin/my.module
路径条目时,将被视为展开的模块。这是因为目录(即顶级目录)module-info.class
中存在一个文件。my.module
- 使用 Maven 等构建工具时也是如此。该
target/classes
目录是一个展开的模块,因为该module-info.class
文件存在于顶级目录中。
- 使用 Maven 等构建工具时也是如此。该
不幸的是,我找不到任何说明上述ModuleFinder
实现在执行时保证在内部使用的内容java
。但是,很可能以上是所使用的。
推荐阅读
- java - db 调用 javax.sql.rowset.spi.SyncFactoryException 中的奇怪错误:找不到资源 javax/sql/rowset/rowset.properties
- csv - 如何将响应数据保存到我在 JMeter 的简单数据编写器中生成的 CSV 文件
- c# - 加载 XAML 设计器时的 C# WPF 错误代码 32
- legend - 高库存。不更新导航器系列可见性
- kubernetes - 在 kubernetes 中找不到 persistentvolumeclaim
- php - 在 Woocommerce 3 中的结帐和我的帐户上启用自定义字段
- java - 使用 PDFBox 在 PDF 中断言文本 - Selenium/java
- python - 如何在 Python 中格式化具有多列但单行的数据框?
- ios - ios swift上的购物添加到购物车图标徽章通知
- sql - 使用 PROC SQL 转置