Java 9错误:不在模块源路径上的模块中

Java 9 error: not in a module on the module source path

项目结构

我有一个用Java 8编写的项目,我想将其更新为Java9。因此,我将类分为2个单独的模块。模组:

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

文件树如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
.
├── 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

1
2
3
4
5
6
7
8
9
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

1
2
3
4
5
6
module pl.edu.prz.klopusz {
    requires org.ggp.base;

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

汇编

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

1
2
3
4
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:

1
error: module not found on module source path

module org.ggp.base {

org.ggp.base包中的类的其他99个错误,每个错误都类似于:

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

1
error: not in a module on the module source path

package external.JSON;

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

1
error: not in a module on the module source path

package org.ggp.base.validator;

我想要的是

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

Package

1
--module-source-path Users/Me/MyProject/src

or if it is in multiple projects, use

1
2
    --module-source-path
        /Users/Me/MyProject/src:/Users/Me/MyOtherProject/src

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

OpenJDK错误站点上也有关于该问题的评论,与我的错误相同,但我想它仍然没有解决。

更新

-verbose开关

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

1
2
3
4
5
6
7
8
9
10
11
[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

的第一行

1
2
3
4
5
6
7
8
9
10
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 {
    //...
}


根据JEP 261,--module-source-path选项(用于在"多模块模式"下进行编译)必须指向一个目录,该目录为每个包含的模块保存一个子目录,该目录名称必须与模块名称相同。

要适应源代码未直接包含在模块目录中的布局,该选项支持以下模式:令牌*可用于表示路径的任何部分(例如,在"./*/src/main/java/"中)的模块名称,该模式将在./my.mod1/src/main/java/module-info.java等中找到模块my.mod1

JEP 261没有提到任何可能出现模式*的约束,但是显然javac不喜欢以*开头的模式。这可能是有意的,也可能不是有意的。

稍有关联,我可能会补充说,在先前的讨论中,我获悉JEP 261包含过时的信息,但我的问题是在JEP完成后是否以及在何处维护此规范,这一问题没有答案。 javac手动输入不是为--module-source-path

之类的选项提供足够详细信息的地方。


出于完整性考虑,完整的javac命令如下:

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

基于来自OpenJDK的官方教程(如下所示略微修改的目录结构)和OpenJDK版本" 11.0.1",上述命令javac对我有效:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
.
├── 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