Java Eclipse可以';在将构建路径切换到JDK 10之后,找不到与XML相关的类

Java Eclipse可以';在将构建路径切换到JDK 10之后,找不到与XML相关的类,java,eclipse,maven,java-10,Java,Eclipse,Maven,Java 10,我正在Eclipse中开发一个分支平台(branchplatform-bom_-brussel-sr7)。当我最近尝试将项目的Java构建路径切换到JDK 10时,Eclipse构建再也找不到诸如javax.xml.xpath.xpath、org.w3c.dom.Document或org.xml.sax.SAXException之类的类。似乎只有与XML相关的类受到影响,主要来自Maven依赖项XML-api-1.4.01 尝试从Eclipse构建Maven不会出错。Ctrl-LeftClick

我正在Eclipse中开发一个分支平台(branchplatform-bom_-brussel-sr7)。当我最近尝试将项目的Java构建路径切换到JDK 10时,Eclipse构建再也找不到诸如
javax.xml.xpath.xpath
org.w3c.dom.Document
org.xml.sax.SAXException
之类的类。似乎只有与XML相关的类受到影响,主要来自Maven依赖项
XML-api-1.4.01

尝试从Eclipse构建Maven不会出错。Ctrl-LeftClick在一个可能缺少的类上找到该类并在Eclipse编辑器中打开它。似乎只有Eclipse构建受到影响

我尝试了几件事,但都没用。我试过:

  • 项目清洁
  • 不同的Eclipse版本:氧气和光子
  • 使用JDK 8和JDK 10运行Eclipse本身
  • 正在更改项目的编译器符合性级别。它使用JDK 8构建路径下的法规遵从性级别8和10构建,而使用JDK 10构建路径下的法规遵从性级别10构建失败

jdk 9+带来了与jigsaw项目相关的变化。JDK被分解成不同的模块,一些模块,javaee、jaxb和xml相关的,默认情况下不再加载。您应该直接将它们添加到maven构建中,而不是期望它们位于jre类路径中。见此

这似乎已被报告为。如果每个人都去投票,也许会让他们提高优先级。

这更多是一个解决办法,但根据我的经验,可以通过转到“Java构建路径”、“订单和导出”选项卡,并将“Maven依赖项”发送到底部(因此它位于“JRE系统库”下方)来解决在Eclipse4.8.0和JDK10下,我们看到了一些非常相似的东西。例如

import org.w3c.dom.Element;
未能在Eclipse中编译:
无法解析导入org.w3c.dom.Element

即便如此,在导入时按F3(打开声明),Eclipse还是能够打开接口定义——在本例中是在
xml-api-1.4.01.jar

同时,Maven direct的构建工作正常

在本例中,修复方法是从
pom.xml
中删除此依赖项:

    <dependency>
        <groupId>xml-apis</groupId>
        <artifactId>xml-apis</artifactId>
        <version>1.4.01</version>
    </dependency>
<dependency>
    <groupId>com.google.code.findbugs</groupId>
    <artifactId>findbugs</artifactId>
    <version>${findbugs.version}</version>
</dependency>

xml API
xml API
1.4.01
然后Eclipse中的编译错误消失了。接下来的F3再次显示了
元素
接口-现在位于项目下JRE系统库下的
java.xml
模块下。此外,Maven的构建仍然很好

这感觉就像Eclipse解析在JDK模块和dependent.jar文件中找到的类时遇到的问题


有趣的是,在一个单独的环境中,这一次是在Eclipse 4.9.0和JDK 11下,无论是否有
XMLAPI:1.4.01
依赖项,一切都很好。

我假设从Java1.8迁移的项目仍然没有
模块信息。Java
。这意味着您正在“未命名模块”中编译代码

未命名模块中的代码“读取”所有可观察的命名和未命名模块,特别是它从JRE系统库中读取模块“java.xml”。此模块导出包,如
java.xml.xpath

此外,类路径上还有
xmlapi.java
,它提供了另一组同名的包(
java.xml.xpath
和friends)。这些被称为与未命名模块相关联,就像您自己的代码一样

这种情况违反了(最后一段)中定义的“唯一可见性”要求。特别是,每个限定类型名Q.Id()都要求其前缀Q是唯一可见的包(为了简单起见,我不考虑嵌套类型的情况)。因此:该程序是非法的,必须被编译器拒绝

这给我们留下了一个问题和两个解决方案:

(1) 问:为什么javac接受这个程序

(2) 解决方案:如果向项目中添加
module info.java
,则可以通过requires控制项目读取的模块,或者
requires java.xml
需要xml.api(其中“xml.api”是“xml-api-1.4.01.jar”的自动模块名)

(3) 解决方案:除了将项目转化为一个模块外,您还可以通过从可观察的模块集中排除
java.xml
来避免冲突。在命令行上,这将使用
--限制模块来完成。Eclipse中的等价物是,另请参见(查找内容选项卡)。由于许多其他默认的可观察模块都隐含地需要
java.xml
,因此最好将
java.base
之外的所有内容从右侧(“显式包含的模块”)推到左侧(“可用模块”)(并有选择地重新添加项目所需的模块)

PS:Eclipse仍然没有提供理想的错误消息,而不是“无法解决”,它实际上应该说:“包javax.xml.xpath可以从多个模块访问:javax.xml

PPS:也很奇怪:为什么更改JRE和类路径上的jar之间的顺序(这种顺序不是javac或JEP261支持的概念)会改变编译器的行为

编辑:

  • Alex Buckley说,不管javac怎么说,给定的情况是非法的。针对javac的Bug已被提出为。这个bug在Java12发布前几个月就被确认了。自2019-06年起,已决定Java 13也将在无需修复的情况下发货。Java14也是如此。该错误暂时被安排在Java15上,但该计划已于2020-04-20取消
  • Eclipse错误消息以提及真正的问题
  • 在Eclipse2019-06中,解决方案(3)所使用的UI已被删除。最新文档可在中找到

这里发生的是一个通配符导入,如

<dependency>
    <groupId>com.google.code.findbugs</groupId>
    <artifactId>findbugs</artifactId>
    <version>${findbugs.version}</version>
    <exclusion>
        <groupId>xml-apis</groupId>
        <artifactId>xml-apis</artifactId>
    </exclusion>
    <exclusion>
        <groupId>jaxen</groupId>
        <artifactId>jaxen</artifactId>
    </exclusion>
</dependency>
    <dependency>
        <groupId>xyz</groupId>
        <artifactId>xyz</artifactId>
        <version>1.0</version>
        <exclusions>
            <exclusion>
                <groupId>xerces</groupId>
                <artifactId>xercesImpl</artifactId>
            </exclusion>
            <exclusion>
                <groupId>xml-apis</groupId>
                <artifactId>xml-apis</artifactId>
            </exclusion>
            <exclusion>
                ...
            </exclusion>
        </exclusions>
    </dependency>