【问题标题】:Java 9 error: not in a module on the module source pathJava 9 错误:不在模块源路径上的模块中
【发布时间】:2018-03-25 13:46:49
【问题描述】:

项目结构

我有一个用 Java 8 编写的项目,我想将它更新到 Java 9。所以我将这些类分成 2 个单独的模块。模块:

  • org.ggp.basemodule-info.java 在目录 org.ggp.base/src/main/java 中。在我开始更新到 Java 9 之前,它的构建是使用 Gradle 自动进行的。该模块使用 pl.edu.prz.klopusz 模块中包含的抽象类实现。
  • pl.edu.prz.klopusz 在目录pl.edu.prz.klopusz/dolar-app/src/main/java 中。我想使用 Maven 自动化它的构建。该模块需要org.ggp.base 模块。

文件树如下所示:

.
├── org.ggp.base/
│   ├── build.gradle
│   └── src/
│       └── main/
│           ├── java/
│           │   ├── external/
│           │   │   └── JSON/
│           │   │       ├── JSONArray.java
│           │   │       └── JSONObject.java
│           │   ├── META-INF/
│           │   │   └── MANIFEST.MF
│           │   ├── module-info.java
│           │   └── org/
│           │       └── ggp/
│           │           └── base/
│           │               └── util/
│           │                   ├── statemachine/
│           │                   │   ├── MachineState.java
│           │                   │   └── StateMachine.java
│           │                   └── symbol/
│           └── resources/
│               └── org/
│                   └── ggp/
│                       └── base/
└── pl.edu.prz.klopusz/
    └── dolar-app/
        └── src/
            └── main/
                └── java/
                    ├── module-info.java
                    └── pl/
                        └── edu/
                            └── prz/
                                └── klopusz/
                                    └── utilities/
                                        └── decorators
                                          └──StateMachineDecorator.java

module-info.java文件的内容如下:

org.ggp.base/src/main/java/module-info.java
module org.ggp.base {
    requires guava;
    requires reflections;
    requires jdk.httpserver;

    uses org.ggp.base.util.statemachine.StateMachine;

    exports org.ggp.base;
}
pl.edu.prz.klopusz/dolar-app/src/main/java/module-info.java
module pl.edu.prz.klopusz {
    requires org.ggp.base;

    provides org.ggp.base.util.statemachine.StateMachine
        with pl.edu.prz.klopusz.utilities.decorators.StateMachineDecorator;
}

编译

我尝试使用以下命令编译项目:

javac -d out \
  --module-source-path org.ggp.base/src/main/java:pl.edu.prz.klopusz/dolar-app/src/main/java \
  $(find org.ggp.base/src/main/java -name *.java) \
  $(find pl.edu.prz.klopusz/dolar-app/src/main/java -name *.java)

错误

我收到以下错误:

org.ggp.base/src/main/java/module-info.java:1:

错误:在模块源路径上找不到模块
模块 org.ggp.base {

org.ggp.base 包内的类还有 99 个其他错误,每个都像:

org.ggp.base/src/main/java/external/JSON/JSONObject.java:1:

错误:不在模块源路径上的模块中
包外部.JSON;

org.ggp.base/src/main/java/org/ggp/base/validator/OPNFValidator.java:1:

错误:不在模块源路径上的模块中
包 org.ggp.base.validator;

我想要什么

我想摆脱错误并编译项目。我不必保留目录结构,但是当我将它们与 2 个 module-info.java 文件放在一起时,编译器抱怨多个模块。我可以通过 IntelliJ IDEA 来完成,我不介意,我试过了。但是我不知道幕后发生了什么,我也不知道如何处理错误(Package is empty: org.ggp.base)。

我已经找到了什么

javac 命令中很难找到关于--module-source-path 开关的文档。 This site is what I found。它说:

如果您在您的 模块,以便您将模块的代码放在封闭的 以模块命名的目录,模块源路径变得更像 一个简单的路径,如
--module-source-path Users/Me/MyProject/src
或者如果它在多个项目中,请使用 --模块源路径 /Users/Me/MyProject/src:/Users/Me/MyOtherProject/src

对于 Windows,使用反斜杠和分号,但无论如何我使用的是 Linux。

还有一个问题on OpenJDK bugs site的评论,和我一样的错误,但我想它仍然没有解决。

更新

-verbose开关

我在命令末尾添加了-verbose 开关。这是编译器所说的一部分:

[parsing started SimpleFileObject[/home/sensitive/org.ggp.base/src/main/java/module-info.java]]
[parsing started SimpleFileObject[/home/sensitive/org.ggp.base/src/main/java/org/ggp/base/util/statemachine/MachineState.java]]
[parsing started SimpleFileObject[/home/sensitive/pl.edu.prz.klopusz/dolar-app/src/main/java/module-info.java]]
[parsing started SimpleFileObject[/home/sensitive/pl.edu.prz.klopusz/dolar-app/src/main/java/pl/edu/prz/klopusz/utilities/decorators/StateMachineDecorator.java]]
org.ggp.base/src/main/java/org/ggp/base/util/statemachine/MachineState.java:1: error: not in a module on the module source path
package org.ggp.base.util.statemachine;
^
[loading /modules/jdk.httpserver/module-info.class]
[loading /modules/java.base/module-info.class]
[total 263ms]
100 errors

所以,我认为这不是--module-source-path 开关中的路径错误(@StephanHerrmann 指出的*src/main/java 也会发生同样的行为)。它读取它应该读取的所有 java 源代码。 pl.edu.prz.klopusz 模块中的源没有问题。 这些是org.ggp.base.util.statemachine.MachineState 的第一行:

package org.ggp.base.util.statemachine;

import org.ggp.base.util.gdl.grammar.GdlSentence;

import java.util.HashSet;
import java.util.Set;

public class MachineState {
    //...
}

【问题讨论】:

  • 我认为--module-source-path 想找到像第一级模块一样命名的目录。 OTOH,如果我正确理解 JEP 261,您也许可以使用*/src/main/java 之类的模式,其中* 代表模块名称。不过,我还没有尝试过。
  • @StephanHerrmann,我使用*/src/main/javaorg.ggp.base/src/main/java:pl.edu.prz.klopusz/dolar-app/src/main/java 都没关系。
  • 您的目录布局不完全符合*/src/main/java 模式,因为额外的dolar-app 中间目录阻止了与模块名称的匹配。
  • 删除dolar-app文件夹并拼接pl.edu.prz.klopuszsrc后,我使用了模式'./*/src/main/java'*/src/main/java'*/src/main/java'org.ggp.base/src/main/java:pl.edu.prz.klopusz/src/main/java 都不起作用。在我使用正确的模式后,错误消失了。所以我想你可以从中做出答案,我会接受的。
  • 接受的答案并没有说明确切的 javac 命令应该是什么样子,你也不知道。为了完整起见,它是javac -d out --module-source-path "./*/src/main/java/" $(find . -name "*.java"),对吧?

标签: java compiler-errors java-9 java-module module-path


【解决方案1】:

根据JEP 261--module-source-path 选项(用于“多模块模式”下的编译)必须指向一个目录,该目录包含每个包含的模块的一个子目录,其中目录名称必须等于模块名称。

为了适应源不直接包含在模块目录中的布局,该选项支持 patterns,其中标记 * 可用于在路径的任何部分表示模块名称,例如在"./*/src/main/java/",它将在./my.mod1/src/main/java/module-info.java等中找到模块my.mod1

JEP 261 没有提及模式* 可能出现的位置的任何限制,但显然javac 不喜欢以* 开头的模式。这可能是故意的,也可能不是故意的。

有点相关,我可能会补充一点,在之前的讨论中,我被告知 JEP 261 包含过时的信息,但我的问题是,在 JEP 完成后是否以及在何处维护该规范,没有得到答案。 javac manual entry 不是为 --module-source-path 等选项提供足够详细信息的地方。

【讨论】:

    【解决方案2】:

    为了完整起见,完整的javac命令如下:

    javac -d out --module-source-path "./*/src/main/java/" $(find . -name "*.java")
    

    基于来自 OpenJDK 的 official tutorial(稍作修改的目录结构如下所示)和 OpenJDK 版本“11.0.1”,上面的命令 javac 对我有效:

    .
    ├── com.greetings
    │   └── src
    │       └── main
    │           └── java
    │               ├── com
    │               │   └── greetings
    │               │       └── Main.java
    │               └── module-info.java
    ├── org.astro
    │   └── src
    │       └── main
    │           └── java
    │               ├── module-info.java
    │               └── org
    │                   └── astro
    │                       └── World.java
    ├── out
    │   ├── classes
    │   │   ├── com.greetings
    │   │   │   ├── com
    │   │   │   │   └── greetings
    │   │   │   │       └── Main.class
    │   │   │   └── module-info.class
    │   │   └── org.astro
    │   │       ├── module-info.class
    │   │       └── org
    │   │           └── astro
    │   │               └── World.class
    │   └── lib
    │       ├── com.greetings.jar
    │       └── org.astro@1.0.jar
    

    【讨论】:

    • 你知道如何使用 Windows 而不是 Linux/Mac OS 编写 javac -d out --module-source-path "./*/src/main/java/" $(find . -name "*.java") 吗?
    • @invzbl3 我相信 powershell 可能会提供一组更有用的命令行实用程序来模仿 Unix find 命令。否则,您当然可以将 bash(或其他)shell 安装到 Windows 中。我认为 Cygwin 是通用/GNU 实现,尽管我只是使用 git 工具为 windows 提供的工具包和 shell。那个 bash shell(我怀疑它无论如何都是 cygwin)工作得很好,并且有“find”和大多数其他工具。学习 bash,你永远不会回头 :)
    • 这是一个老问题,但以防万一有人偶然发现:你应该可以在 Windows cmd 中执行:dir /s /b *.java > mySourceFiles.txt & javac -d out --模块源路径 ".*\src\main\java\" @sourceFiles.txt &del mySourceFiles.txt
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-17
    • 2018-03-10
    • 2019-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多