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

Java JDK11迁移:Eclipse 2018-12中显示编译错误,但代码运行正常,java,java-module,java-11,Java,Java Module,Java 11,在使用Eclipse2018-12从OracleJDK8迁移到OpenJDK11.0.1的过程中,我显然发现了另一个与JPMS相关的bug,这使得在模块化java项目中使用外部非模块化的.jar非常困难。我将我的问题追溯到下面的完整示例 该示例源自一个实际项目的迁移过程(使用仍然未模块化的javax.servlet.api),这导致了一些麻烦。它由四个maven项目M、N、Y和X组成,每个项目组成一个java模块,另一个maven项目组成一个非模块化java项目W。我使用maven和maven编

在使用Eclipse2018-12从OracleJDK8迁移到OpenJDK11.0.1的过程中,我显然发现了另一个与JPMS相关的bug,这使得在模块化java项目中使用外部非模块化的.jar非常困难。我将我的问题追溯到下面的完整示例

该示例源自一个实际项目的迁移过程(使用仍然未模块化的javax.servlet.api),这导致了一些麻烦。它由四个maven项目M、N、Y和X组成,每个项目组成一个java模块,另一个maven项目组成一个非模块化java项目W。我使用maven和maven编译器插件3.8.0。我的意见是:

  • Eclipse在M.java中显示错误,但运行带有默认选项的类M时不会出现错误
  • 如果我将工件w作为附加的maven依赖项包含在项目M中,那么错误仍然存在
  • 如果我将项目Y和工件、包名和模块信息一起重命名为项目O,则不会显示任何错误
  • 如果我删除模块m中的requires w,则不会显示任何错误
  • 如果通过添加module-info.java使project W模块化,则不会显示任何错误
  • 如果我通过在MANIFEST.MF中添加自动模块名:W使项目W模块化,错误仍然存在
显然,在顶级项目中重新声明像模块w这样的自动化模块似乎会导致内置Eclipse编译器出现问题,并且不允许我们在Eclipse中正常工作(而运行项目效果很好)。在我看来,这种不匹配是Eclipse 2018-12中的另一个bug(以及我在和中描述的问题)

我的问题是:有人能确认这是一个bug吗,还是已经知道了?对于我们来说,这是一个完全的阻碍,因为我们的项目依赖于不同的库,这些库既不是模块化的,也没有自动模块名属性。只要本文中描述的Eclipse错误存在,我们就无法进一步迁移到JDK 11。

Sidemark:我们不想在从SCM签出后配置我们的项目以使其在Eclipse中运行。对我们来说,这直到现在才是必要的(在使用Maven和Eclipse时,这真的很棒,感谢到目前为止使这成为可能的所有人!),我几乎不想避免手动配置Eclipse项目的模块路径或运行配置


下面是一个完整且可复制的示例:

项目M(模块化)

//M.java
包m;
导入com.example.n.n;
公共级M{
公共静态void main(字符串[]args){
系统输出打印项次(“M”);
N.main(空);
}
}
//module-info.java
开模m{
需要n;
需要w;
}
//pom.xml
4.0.0
com.mavenexample2

实际上,Eclipse有一个bug,只有在按照非常特定的顺序执行编译时才会出现

背景:在JPMS时代,软件包有不同的内容 取决于所询问的模块。在本例中,使用不同的模块 查看包
com的不同配置。示例
:来自一些 p、 o.v.在其他透视图中,它包含一个子包
n
不。出于性能考虑,将缓存此类查找的每个结果, 这导致了顺序依赖性:哪个模块首先查找 包
com。示例
决定了对包的贡献
知道

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


(已编辑:)该漏洞已被解决为,自2019-03发布以来,该修复程序已可用。

Eclipse 2018-12有许多漏洞。。。我更喜欢Eclipse4.7.3,尽管它不支持Java11。或者只是使用这个想法。@Eric Wang:谢谢你的建议。对于Eclipse,我提交了一份bug报告,因为所描述的问题将成为我们在使用Eclipse时的一个障碍:到目前为止,Eclipse中还没有发现bug。必须通过jar文件访问自动模块。M需要依赖于w,因为
需要w
来解析。通过这些观察点,可以按照设计完成编译和运行工作。@StephanHerrmann:如果w安装在.m2中,并在之后关闭,则可以通过.jar文件访问自动模块w。M已经(间接)依赖于w(M依赖于Y依赖于X依赖于w)。在我看来,这两个需求都得到了满足,但是Eclipse仍然在类M中显示错误消息(而这个类是按预期运行的)。请参阅中的我的评论。在识别复制步骤中的打字错误(在本问题中也可见)后,可以复制仅限编辑的错误标记。这不应该妨碍开发,但当然还需要在Eclipse中修复。
// 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.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.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.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.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>