JDK11 迁移:Eclipse 2018-12 中显示编译错误,但代码运行正常
JDK11 Migration: Compilation error shown in Eclipse 2018-12 but code runs fine
从 Oracle JDK 8 迁移到 Open JDK 11.0.1 使用 Eclipse 2018-12 我显然发现了另一个与 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 中显示错误,但 运行ning class M 使用默认选项运行s 没有错误
- 如果我在项目 M 中将工件 w 作为附加的 Maven 依赖项包含在内,错误仍然存在
- 如果我将项目 Y 重命名为项目 O 以及工件、包名称和模块信息,则不会显示任何错误
- 如果我删除模块 m 中的 requires w,则不会显示任何错误
- 如果我通过添加 模块-info.java 使项目 W 模块化,则不会显示任何错误
- 如果我通过在 [=129= 中添加 Automatic-Module-Name: w 使项目 W 模块化],错误依旧
显然,在顶级项目中重新声明模块 w 等自动化模块 似乎会导致内置 Eclipse 编译器出现问题 并且不允许我们使用 Eclipse 正常工作(而 运行ning 项目运行良好)。在我看来,这种不匹配是 Eclipse 2018-12 中的另一个错误(以及我在 and Java module not found at runtime even with requires transitive 中描述的问题)。
我的问题是:有人可以确认这是一个错误,还是已经知道了?对我们来说,这是一个完全的阻碍,因为我们的项目依赖于不同的库,这些库既不是模块化的,也没有 Automatic-Module-Name 属性。只要 post 中描述的 Eclipse 错误存在,我们就无法进一步迁移到 JDK 11.
Sidemark:我们不想在从 SCM 签出后配置我们的项目以在 Eclipse 中获取它 运行ning。对我们来说,直到现在都没有必要(在使用 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 > 更新项目... > 全部以在定义项目或更改模块依赖项后同步所有内容。此外,请在执行 mvn clean install 后关闭非模块化项目 M,否则您将收到此处描述的错误:.
Eclipse 确实有一个错误,只有在以非常特定的顺序执行编译时才会出现该错误。
Background: In the era of JPMS a package has different content
depending on which module is asking. In the example different modules
see different configurations for package com.example
: from some
p.o.v. it contains a child package n
in other perspectives it
doesn't. For performance sake, each result of such lookup is cached,
which caused the order dependence: which module first looked up
package com.example
decided what contributions to the package were
known.
Curiously, the same JPMS that makes split packages illegal, requires a compiler to treat each parent package with multiple contributing modules as a split package, causing a significant increase in implementation complexity.
(已编辑:) 该错误已解决为 Eclipse bug 543765,此修复自 2019-03 版以来可用。
从 Oracle JDK 8 迁移到 Open JDK 11.0.1 使用 Eclipse 2018-12 我显然发现了另一个与 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 中显示错误,但 运行ning class M 使用默认选项运行s 没有错误
- 如果我在项目 M 中将工件 w 作为附加的 Maven 依赖项包含在内,错误仍然存在
- 如果我将项目 Y 重命名为项目 O 以及工件、包名称和模块信息,则不会显示任何错误
- 如果我删除模块 m 中的 requires w,则不会显示任何错误
- 如果我通过添加 模块-info.java 使项目 W 模块化,则不会显示任何错误
- 如果我通过在 [=129= 中添加 Automatic-Module-Name: w 使项目 W 模块化],错误依旧
显然,在顶级项目中重新声明模块 w 等自动化模块 似乎会导致内置 Eclipse 编译器出现问题 并且不允许我们使用 Eclipse 正常工作(而 运行ning 项目运行良好)。在我看来,这种不匹配是 Eclipse 2018-12 中的另一个错误(以及我在
我的问题是:有人可以确认这是一个错误,还是已经知道了?对我们来说,这是一个完全的阻碍,因为我们的项目依赖于不同的库,这些库既不是模块化的,也没有 Automatic-Module-Name 属性。只要 post 中描述的 Eclipse 错误存在,我们就无法进一步迁移到 JDK 11.
Sidemark:我们不想在从 SCM 签出后配置我们的项目以在 Eclipse 中获取它 运行ning。对我们来说,直到现在都没有必要(在使用 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 > 更新项目... > 全部以在定义项目或更改模块依赖项后同步所有内容。此外,请在执行 mvn clean install 后关闭非模块化项目 M,否则您将收到此处描述的错误:
Eclipse 确实有一个错误,只有在以非常特定的顺序执行编译时才会出现该错误。
Background: In the era of JPMS a package has different content depending on which module is asking. In the example different modules see different configurations for package
com.example
: from some p.o.v. it contains a child packagen
in other perspectives it doesn't. For performance sake, each result of such lookup is cached, which caused the order dependence: which module first looked up packagecom.example
decided what contributions to the package were known.Curiously, the same JPMS that makes split packages illegal, requires a compiler to treat each parent package with multiple contributing modules as a split package, causing a significant increase in implementation complexity.
(已编辑:) 该错误已解决为 Eclipse bug 543765,此修复自 2019-03 版以来可用。