在使用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。我的观察是:
显然,在顶级项目中重新声明模块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 bug存在,我们就无法进一步迁移到JDK 11。
Sidemark:我们不希望在从SCM退出后让它在Eclipse中运行时配置我们的项目。对我们来说,直到现在还没有必要(当使用Maven和Eclipse时,实际上真的非常棒,感谢迄今为止所有人都做到了!),我几乎不会试图避免手动配置我们的eclipse项目的模块路径或者运行配置。
所以,这是完整且可重复的示例:
项目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>
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>更新项目...> all以在定义项目或更改模块依赖项后使所有内容保持同步。此外,请在执行mvn clean安装后关闭非模块化项目M,否则您将收到此处描述的错误:Automatic modules not found in Eclipse 2018-12 when project is opened。
事实上,Eclipse有一个bug,只有在以非常特定的顺序执行编译时才出现。
背景:在JPMS时代,一个包具有不同的内容,具体取决于所询问的模块。在示例中,不同的模块可以看到包
com.example
的不同配置:来自某些p.o.v.它包含一个子包n
在其他方面它没有。为了性能起见,这种查找的每个结果都被缓存,这导致顺序依赖:哪个模块首先查找包com.example
决定了对包的贡献是什么。奇怪的是,使拆分包非法的相同JPMS需要编译器将具有多个贡献模块的每个父包视为拆分包,从而导致实现复杂性的显着增加。
(已编辑:)该错误已被解决为Eclipse bug 543765,修复程序自2019-03发布以来可用。