【发布时间】:2019-01-23 14:07:16
【问题描述】:
在使用 Eclipse 2018-12 从 Oracle JDK 8 迁移到 Open JDK 11.0.1 时,我显然发现了另一个与 JPMS 相关的错误在模块化 java 项目中很难使用外部非模块化 .jar。我将我的问题追溯到下面的完整示例。
该示例源自一个实际项目的迁移过程(使用仍然未模块化的javax.servlet.api),这引起了一些麻烦。它由四个 maven 项目 M、N、Y 和 X 组成,每个项目组成一个 java 模块,另一个 maven 项目组成一个非模块化 java 项目 W。我使用 maven 和 maven-compiler-plugin 3.8.0。我的观察是:
- Eclipse 在 M.java 中显示错误,但使用默认选项运行类 M 运行时没有错误
- 如果我将工件 w 作为附加的 maven 依赖项包含在项目 M 中,错误仍然存在
- 如果我将项目 Y 连同工件、包名和模块信息重命名为项目 O,则不会显示任何错误
- 如果我删除模块 m 中的 requires w,则不会显示任何错误
- 如果我通过添加 module-info.java 使项目 W 模块化,则不会显示任何错误
- 如果我通过在 MANIFEST.MF 中添加 Automatic-Module-Name: w 使项目 W 模块化,错误仍然存在
显然,在顶级项目中重新声明像模块 w 这样的自动化模块似乎会导致内置 Eclipse 编译器出现问题,并且不允许我们工作正确使用 Eclipse(而运行项目运行良好)。在我看来,这种不匹配是 Eclipse 2018-12 中的另一个错误(以及我在 Automatic modules not found in Eclipse 2018-12 when project is opened 和 Java module not found at runtime even with requires transitive 中描述的问题)。
我的问题是:有人可以确认这是一个错误,还是已经知道?对我们来说,这是一个完整的展示停止器,因为我们的项目依赖于不同的库,这些库既不是模块化的,也没有 Automatic-Module-Name 属性。只要本文中描述的 Eclipse 错误存在,我们就无法进一步迁移到 JDK 11。
Sidemark:我们不想在从 SCM 签出后配置我们的项目以使其在 Eclipse 中运行。对我们来说,直到现在还没有必要(在使用 Maven 和 Eclipse 时,这实际上非常棒,感谢迄今为止让这一切成为可能的所有人!),我几乎不会避免手动配置我们的 Eclipse 项目或运行配置的模块路径。
所以,这里是完整且可重现的示例:
Project M(模块化)
// M.java
package m;
import com.example.n.N;
public class M {
public static void main(String[] args) {
System.out.println("M");
N.main(null);
}
}
// module-info.java
open module m {
requires n;
requires w;
}
// pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mavenexample2</groupId>
<artifactId>m</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>com.mavenexample2</groupId>
<artifactId>n</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.mavenexample2</groupId>
<artifactId>y</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
项目 N(模块化)
// N.java
package com.example.n;
public class N {
public static void main(String[] args) {
System.out.println("N");
}
}
// module-info.java
open module n {
exports com.example.n;
}
// pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mavenexample2</groupId>
<artifactId>n</artifactId>
<version>0.0.1-SNAPSHOT</version>
</project>
Y 项目(模块化)
// Y.java
package com.example.y;
public class Y {
public static void main(String[] args) {
System.out.println("Y");
}
}
// module-info.java
open module com.example.y {
exports com.example.y;
requires com.example.x;
}
// pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mavenexample2</groupId>
<artifactId>y</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>com.mavenexample2</groupId>
<artifactId>x</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
Project X(模块化)
// X.java
package com.example.x;
public class X {
public static void main(String[] args) {
System.out.println("X");
}
}
// module-info.java
open module com.example.x {
exports com.example.x;
requires w;
}
// pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mavenexample2</groupId>
<artifactId>x</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>com.mavenexample2</groupId>
<artifactId>w</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
W 项目(非模块化)
// W.java
package external;
public class W {
public static void main(String[] args) {
System.out.println("W");
}
}
// pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mavenexample2</groupId>
<artifactId>w</artifactId>
<version>0.0.1-SNAPSHOT</version>
</project>
请在定义项目或更改模块依赖项后执行 Maven > Update Projects ... > 以使所有内容保持同步。另外,请在执行 mvn clean install 后关闭非模块化项目 M,否则您会收到此处描述的错误:Automatic modules not found in Eclipse 2018-12 when project is opened。
【问题讨论】:
-
Eclipse 2018-12 有很多错误......我更喜欢 Eclipse 4.7.3 虽然它不支持 Java 11。或者只是使用 IDEA。
-
@Eric Wang:感谢您的建议。对于 Eclipse,我提交了一个错误报告,因为所描述的问题将成为我们使用 Eclipse 时的障碍:bugs.eclipse.org/bugs/show_bug.cgi?id=543765
-
到目前为止,还没有发现 Eclipse 中的错误。 必须通过 jar 文件访问自动模块。 M 需要依赖 w 来解决
requires w。根据这些点观察编译和运行按设计工作。 -
@StephanHerrmann:如果 W 安装在 .m2 中并随后关闭,则通过 .jar 文件访问自动模块 w。 M 已经对 w 有一个(间接)依赖(M 依赖于 Y 依赖于 X 依赖于 W)。在我看来,这两个要求都得到了满足,但 Eclipse 仍然在类 M 中显示错误消息(而 按预期运行这个类)。请在bugs.eclipse.org/bugs/show_bug.cgi?id=543765 中查看我的cmets。
-
在确定重现步骤中的错字后(在此问题中也可见),可以重现仅编辑器的错误标记。这不应该阻碍开发,但当然仍然需要在 Eclipse 中修复。
标签: java java-module java-11