首页 文章

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

提问于
浏览
3

项目结构

我有一个用Java 8编写的项目,我想将它更新为Java 9.所以我把这些类分成了两个独立的模块 . 模块:

  • org.ggp.basemodule-info.java 目录为 module-info.java . 在我开始更新Java 9之前,它的构建是使用Gradle自动完成的 . 该模块使用 pl.edu.prz.klopusz 模块中包含的抽象类实现 .

  • pl.edu.prz.klopuszpl.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:错误:不在模块源路径包external.JSON上的模块中;

要么

org.ggp.base / src / main / java / org / ggp / base / validator / OPNFValidator.java:1:错误:不在模块源路径包org.ggp.base.validator上的模块中;

我想要什么

我想摆脱错误并编译项目 . 我没有保留目录结构,但是当我把所有内容放在一起时,编译器抱怨了多个模块 . 我可以通过IntelliJ IDEA完成它,我不知道幕后发生了什么,我也不知道如何处理错误( Package is empty: org.ggp.base ) .

Package is empty: org.ggp.base

我已经找到了什么

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

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

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

还有一个问题on OpenJDK bugs site的评论,与我的错误相同,但我想它仍未解决 .

UPDATE

-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 {
    //...
}

2 回答

  • 6

    根据JEP 261--module-source-path 选项(用于"multi-module mode"中的编译)必须指向一个目录,该目录包含每个包含模块的一个子目录,其中目录名称必须等于模块名称 .

    为了适应模块目录中不直接包含源的布局,该选项支持模式,其中令牌 * 可用于表示路径任何部分中的模块名称,例如 "./*/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
    

相关问题