JDK11迁移:Eclipse 2018-12中显示了编译错误,但代码运行正常

时间:2019-01-23 14:07:16

标签: java java-module java-11

使用 Eclipse 2018-12 Oracle JDK 8 迁移到 Open JDK 11.0.1 时,我显然发现了另一个与JPMS相关的错误很难在模块化Java项目中使用外部未模块化的 .jar's 。我将问题追溯到下面的完整示例。

该示例来自真实项目的迁移过程(使用仍未模块化的 javax.servlet.api ),这引起了一些麻烦。它由四个分别构成一个Java模块的Maven项目 M,N,Y和X 和另一个构成一个非模块化Java项目 W 的maven项目组成。我使用了maven和 maven-compiler-plugin 3.8.0 。我的观察是:

  • Eclipse在 M.java 中显示错误,但是运行带有默认选项的类 M 却没有错误
  • 如果我将工件 w 作为附加的maven依赖项包含在项目 M 中,则错误仍然存​​在
  • 如果我将项目 Y 重命名为项目 O 以及工件,程序包名称和模块信息,则不会显示错误
  • 如果我删除模块 m 中的要求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 openedJava module not found at runtime even with requires transitive中描述的问题)。

我的问题是:有人可以确认这是一个错误,还是已经知道?对我们来说,这是一个完整的展示机会,因为我们的项目依赖于既不是模块化也不是 Automatic-Module-Name 属性的不同库。只要存在本文中描述的Eclipse错误,我们就无法进一步迁移到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>

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全新安装之后,也请关闭非模块化项目 M ,因为否则您将得到此处描述的错误:Automatic modules not found in Eclipse 2018-12 when project is opened

1 个答案:

答案 0 :(得分:2)

确实,Eclipse有一个bug,仅当以非常特定的顺序执行编译时才会出现。

  

背景:在JPMS时代,程序包具有不同的内容   取决于询问哪个模块。在示例中,不同的模块   查看软件包com.example的不同配置:   p.o.v.从其他角度来看,它包含一个子程序包n   没有。为了提高性能,此类查询的每个结果都会被缓存,   哪个导致了订单依赖性:首先查找哪个模块   软件包com.example决定了对软件包的贡献   

     

奇怪的是,将拆分程序包定为非法的同一JPMS,要求编译器将具有多个贡献模块的每个父程序包都视为拆分程序包,从而大大增加了实现复杂性。

(已编辑:)该错误已解决为Eclipse bug 543765,此修复程序自2019-03版本以来可用。