【问题标题】:JDK11 Migration: Compilation error shown in Eclipse 2018-12 but code runs fineJDK11 迁移:Eclipse 2018-12 中显示编译错误,但代码运行良好
【发布时间】:2019-01-23 14:07:16
【问题描述】:

在使用 Eclipse 2018-12Oracle 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 作为附加的 maven 依赖项包含在项目 M 中,错误仍然存​​在
  • 如果我将项目 Y 连同工件、包名和模块信息重命名为项目 O,则不会显示任何错误
  • 如果我删除模块 m 中的 requires 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 项目或运行配置的模块路径。


所以,这里是完整且可重现的示例:

Project 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>

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 > Update Projects ... > 以使所有内容保持同步。另外,请在执行 mvn clean install 后关闭非模块化项目 M,否则您会收到此处描述的错误:Automatic modules not found in Eclipse 2018-12 when project is opened

【问题讨论】:

  • Eclipse 2018-12 有很多错误......我更喜欢 Eclipse 4.7.3 虽然它不支持 Java 11。或者只是使用 IDEA。
  • @Eric Wang:感谢您的建议。对于 Eclipse,我提交了一个错误报告,因为所描述的问题将成为我们使用 Eclipse 时的障碍:bugs.eclipse.org/bugs/show_bug.cgi?id=543765
  • 到目前为止,还没有发现 Eclipse 中的错误。 必须通过 jar 文件访问自动模块。 M 需要依赖 w 来解决 requires w。根据这些点观察编译和运行按设计工作。
  • @StephanHerrmann:如果 W 安装在 .m2 中并随后关闭,则通过 .jar 文件访问自动模块 w。 M 已经对 w 有一个(间接)依赖(M 依赖于 Y 依赖于 X 依赖于 W)。在我看来,这两个要求都得到了满足,但 Eclipse 仍然在类 M 中显示错误消息(而 按预期运行这个类)。请在bugs.eclipse.org/bugs/show_bug.cgi?id=543765 中查看我的cmets。
  • 在确定重现步骤中的错字后(在此问题中也可见),可以重现仅编辑器的错误标记。这不应该阻碍开发,但当然仍然需要在 Eclipse 中修复。

标签: java java-module java-11


【解决方案1】:

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

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

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

(已编辑:) 该错误已解决为 Eclipse bug 543765,自 2019-03 版本起提供修复。

【讨论】:

    猜你喜欢
    • 2017-06-15
    • 1970-01-01
    • 2015-09-26
    • 1970-01-01
    • 2016-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-06
    相关资源
    最近更新 更多