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。我的观察是:

显然,在顶级项目中重新声明模块 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 版以来可用。