【问题标题】:Java 9: Possible to have 2 modules with same name on module pathJava 9:模块路径上可能有 2 个同名模块
【发布时间】:2017-10-04 20:24:58
【问题描述】:

模块路径上是否可以有两个名称完全相同(但内容略有不同)的模块?

据我所知,Java 9 编译器并没有抱怨它。我有 2 个模块声明如下:

module com.dj.helper {
    exports com.dj.helper;
}

两者都包含com.dj.helper 包,但包内的内容不同。然后在我的主应用程序中,我希望导入这个模块:

module com.dj {
    requires com.dj.helper;
}

同名的两个模块都在我的模块路径上。

我希望在编译我的 com.dj 模块时,编译器会抱怨同一个模块存在两次,但事实并非如此。这是否实际上意味着您的模块路径上可能有同一个 jar 的 2 个版本,而 Java 将不知道该使用哪一个?

【问题讨论】:

    标签: java java-9 java-module module-info


    【解决方案1】:

    没有

    在模块路径的同一目录中不可能有两个同名的模块。官方文档并没有将这些信息放在特别突出的位置 - 它是 the Javadoc of ModuleFinder::of 泄露它:

    如果一个目录包含多个同名模块,则会出错。

    我通过创建同一模块的两个版本来创建 a small demo project for the module systemit covers that case...

    jar --create
        --file mods/monitor.observer.beta-1.0.jar
        --module-version 1.0
        -C classes/monitor.observer.beta .
    jar --create
        --file mods/monitor.observer.beta-2.0.jar
        --module-version 2.0
        -C classes/monitor.observer.beta .
    

    ...然后在下次编译时引用该文件夹...

    javac
        --module-path mods
        -d classes/monitor.statistics
        $(find monitor.statistics -name '*.java')
    

    ...正如预期的那样导致以下错误消息:

    error: duplicate module on application module path
    module in monitor.observer.beta
    1 error
    

    注意我说的是在同一个目录。跨目录多个模块是可能的。

    是的

    模块系统只强制目录中的唯一性。再次来自ModuleFinder::of(强调我的):

    模块查找器通过按数组索引顺序搜索每个目录、展开的模块或打包的模块来定位模块。它查找具有给定名称的模块的第一次出现并忽略序列中稍后出现的具有该名称的其他模块

    这使得在不同目录中拥有相同的模块成为可能。

    【讨论】:

    • 可能是因为限制仅适用于同一目录中的相同模块吗?这就是我理解 JEP 和您链接的页面中的规范的方式。
    • 您的 monitor.statistics 模块不应该依赖于 monitor.observer.beta 吗?
    • @manouti 哦,你说得对!我忘记了。将更新答案。
    • @DJ180 有趣的是,即使没有这种依赖,它也能打破。
    • 这让我很困惑!
    【解决方案2】:

    模块系统的JEP 261描述模块路径如下:

    模块路径是一个序列,其中的每个元素要么是一个模块定义,要么是一个包含模块定义的目录。每个模块定义要么是

    • 模块工件,即包含已编译模块定义的模块化 JAR 文件或 JMOD 文件,否则

    • 一个exploded-module 目录,按照惯例,它的名称是模块的名称,其内容是对应于包层次结构的“exploded”目录树。

    然后描述模块解析机制:

    在模块路径中搜索具有特定名称的模块时,模块系统会采用该名称模块的第一个定义。版本字符串(如果存在)将被忽略; 如果模块路径的一个元素包含多个同名模块的定义,则解析失败,编译器、链接器或虚拟机将报告错误并退出。这是构建工具的责任和容器应用配置模块路径,避免版本冲突;解决版本选择问题不是模块系统的目标。

    如上所述,这意味着只有当两个同名模块存在于同一目录中时,编译器才会报错。

    【讨论】:

    • jar 文件上下文中的目录是什么意思?我认为这行说明:“模块系统采用该名称的模块的第一个定义”。当然这意味着我们仍然会遇到很多运行时类路径问题?
    • @DJ180 规范中提到的目录是包含模块定义的目录(即模块化Jar,或包含模块定义文件和包的分解目录)。我还不清楚这是否会导致运行时问题(我还没有尝试过这种情况)。
    猜你喜欢
    • 1970-01-01
    • 2018-09-17
    • 1970-01-01
    • 1970-01-01
    • 2016-02-19
    • 1970-01-01
    • 2019-10-07
    • 1970-01-01
    相关资源
    最近更新 更多