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

问题描述 投票:1回答:1

在使用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作为项目M中的附加maven依赖项包含在内,则错误仍然存​​在
  • 如果我将项目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 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

java java-module java-11
1个回答
2
投票

事实上,Eclipse有一个bug,只有在以非常特定的顺序执行编译时才出现。

背景:在JPMS时代,一个包具有不同的内容,具体取决于所询问的模块。在示例中,不同的模块可以看到包com.example的不同配置:来自某些p.o.v.它包含一个子包n在其他方面它没有。为了性能起见,这种查找的每个结果都被缓存,这导致顺序依赖:哪个模块首先查找包com.example决定了对包的贡献是什么。

奇怪的是,使拆分包非法的相同JPMS需要编译器将具有多个贡献模块的每个父包视为拆分包,从而导致实现复杂性的显着增加。

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

© www.soinside.com 2019 - 2024. All rights reserved.