将构建路径切换到 JDK 10 后,Eclipse 找不到 XML 相关的 类
Eclipse can't find XML related classes after switching build path to JDK 10
我正在 Eclipse 中开发 Maven project(分支 platform-bom_brussels-sr7)。当我最近尝试将项目的 Java Build Path 切换到 JDK 10 时,Eclipse build 再也找不到 classes such as javax.xml.xpath.XPath
, org.w3c.dom.Document
,或 org.xml.sax.SAXException
。似乎只有 XML 相关的 classes 受到影响,主要来自 Maven 依赖项 xml-apis-1.4.01
.
尝试从 Eclipse 构建 Maven 没有错误。按住 Ctrl-左键单击其中一个据称缺失的 classes 会找到 class 并在 Eclipse 编辑器中将其打开。似乎只有 Eclipse 构建受到影响。
我尝试了几件事,但 none 有所帮助。我试过了:
- 清理项目
- 不同的 Eclipse 版本:氧气和光子。
- 运行 Eclipse 自身 JDK 8 和 JDK 10。
- 正在更改项目的编译器合规性级别。它在 JDK 8 构建路径下以合规级别 8 和 10 构建,并且在构建路径中使用 JDK 10 时都失败。
jdk 9+ 带来了与拼图项目相关的变化。 JDK 被分解成各种模块,一些模块,javaee,jaxb 和 xml 相关,默认情况下不再加载。您应该将它们直接添加到您的 Maven 构建中,而不是期望它们位于 jre 类路径中。看到这个
这似乎被报告为 Eclipse Bug 536928。也许如果每个人都去投票,他们会提高优先级。
这更像是一种解决方法,但根据我的经验,可以通过转到 "Java Build Path"、"Order and Export" 选项卡并将 "Maven Dependencies" 发送到底部(所以它在 "JRE System Library" 下方)。
在 Eclipse 4.8.0 和 JDK 10 下看到了非常相似的东西。例如
import org.w3c.dom.Element;
无法在 Eclipse 中编译:The import org.w3c.dom.Element cannot be resolved
即便如此,在该导入上按 F3(打开声明),Eclipse 仍能够打开接口定义 - 在本例中为 xml-apis-1.4.01.jar
.
与此同时,直接从 Maven 构建工作正常。
在这种情况下,修复是从 pom.xml
:
中删除此依赖项
<dependency>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
<version>1.4.01</version>
</dependency>
然后 Eclipse 中的编译错误消失了。按照F3再次显示Element
界面——现在在java.xml
模块下,在项目下的JRE系统库下。 Maven 构建也保持良好。
这感觉像是 Eclipse 解决它在 JDK 模块和相关 .jar 文件中发现的 class 的问题。
有趣的是,在单独的环境中,这次在 Eclipse 4.9.0 和 JDK 11 下,一切都很好,有或没有 xml-apis:1.4.01
依赖项。
我假设正在从Java 1.8 迁移的项目仍然没有module-info.java
。这意味着您正在 "unnamed module".
中编译代码
未命名模块中的代码 "reads" 所有可观察的命名和未命名模块,特别是它从 JRE 系统库中读取模块 "java.xml"。此模块导出包,如 java.xml.xpath
.
此外,您在类路径上有 xml-apis.java
,它提供了另一组同名包(java.xml.xpath
和朋友)。这些据说与未命名模块相关联,就像您自己的代码一样。
这种情况违反了"unique visibility"中定义的要求JLS §7.4.3 (last paragraph). In particular every qualified type name Q.Id (JSL §6.5.5.2)要求其前缀Q是唯一可见的包(我无视为简单起见,嵌套类型的情况)。因此:该程序是非法的,必须被编译器拒绝。
这留给我们一个问题和两个解决方案:
(1)问题:javac为什么接受程序?
(2)解决方案:如果你在项目中添加module-info.java
,你可以通过requires来控制你的项目读取哪个模块,requires java.xml;
或者requires xml.apis;
(其中 "xml.apis" 是“xml-apis-1.4.01.jar”的自动模块名称)。
(3) 解决方案:如果不将您的项目转换为模块,您仍然可以通过从可观察模块集中排除 java.xml
来避免冲突。在命令行上,这将使用 --limit-modules
完成。 Eclipse 中的等效项是 "Modularity Details" dialog, see also the JDT 4.8 New&Noteworthy(查找 Contents 选项卡)。由于 java.xml
是通过许多其他默认可观察模块隐式需要的,因此将 java.base
以外的所有内容从右 ("Explicitly included modules") 推到左 ([=70) 可能是个好主意=])(并有选择地重新添加项目需要的那些模块)。
PS:Eclipse 仍然没有提供理想的错误消息,而不是 "cannot be resolved" 它实际上应该说:“包 javax.xml.xpath 可以从多个模块访问: javax.xml、<未命名>。
PPS:也很奇怪:为什么更改类路径上 JRE 和 jar 之间的顺序(这种顺序不是 javac 或 JEP 261 支持的概念)会改变编译器的行为。
编辑:
- 亚历克斯·巴克利 confirmed that the given situation is illegal, despite what javac says. Bug against javac has been raised as JDK-8215739。此错误已在 Java 12 发布前几个月得到确认。截至 2019 年 6 月,已决定 Java 13 也将在没有修复的情况下发布。 Java 14 也是如此。该错误暂时安排在 Java 15,但该计划已于 2020-04-20 取消。
- Eclipse 报错信息has been improved提一下真正的问题。
- 在 Eclipse 2019-06 中,用于解决方案 (3) 的 UI 已 revamped. Up-to-date documentation can be found in the online help。
这里发生了什么 你有一个像 import org.w3c.dom.*
这样的通配符导入,说明你想从包 org.w3c.dom
导入所有 classes .现在,如果第二个来源提供的 org.w3c.dom
中至少有一个 class,则 Java 不能启动(正如 所指出的)。
(顺便说一下,消息“...无法解析”被更准确的错误消息“The package org.w3c.dom 可从多个模块访问:, java.xml " 在较新的 Eclipse 版本中,请参阅 Stephan Herrmann 合并的 change request。)
解决这个问题
- 打开"Open Type"对话框(Ctrl+Shift+T) .
- 输入完成导入,所以
org.w3c.dom.*
或org.w3c.dom.
.
- 检查整个列表是否有多个来源。此处的所有条目应仅包含类似 "jdk-11-...".
的内容
- 收集所有包含 class您有多个来源的 JAR。
- 从
pom.xml
打开 "Dependency Hirarchy" 选项卡。
- 搜索 JAR 文件。
- 添加排除项(右键单击或手动编辑
pom.xml
)。
例子
我的 pom.xml
:
中有这个 findbugs 依赖项
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>findbugs</artifactId>
<version>${findbugs.version}</version>
</dependency>
Findbugs 有两个需要排除的依赖项:
<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>
在我的例子中,问题是 xercesImpl : 2.10.0
是一个(暂时的)依赖。这个 jar 包 org.w3c.dom.html.HTMLDOMImplementation
.
据我了解,org.w3c.dom
包随后可从两个模块获得,导致构建失败。
如果其中一个依赖项(直接或瞬态)在 java.xml module 导出的 25 个包之一中具有 类,您的构建将失败。
在 Maven 中排除 xercesImpl(以及下面列出的违规者)为我解决了这个问题:
<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>
感谢 Rune Flobakk 在这里给出提示:https://bugs.eclipse.org/bugs/show_bug.cgi?id=536928#c73
其他违规者:
batik-ext : 1.9
(捆绑组织。w3c.dom.Window)
xom : 1.2.5
(捆绑组织。w3c.dom.UserDataHandler)
stax-api : 1.0.2
(捆绑包 javax.xml.stream.EventFilter)
xml-apis : 1.4.01
(捆绑组织。w3c.dom.Document)
xml-beans : 2.3.0
(捆绑组织。w3c.dom.TypeInfo)
虽然 Stephan Herrmann 的回答是正确的,但我会 post 我的错误以及我是如何解决它的,如果它可以帮助其他人的话。我有错误 The package javax.xml.namespace is accessible from more than one module: <unnamed>, java.xml
并且在检查 class 错误之后,是 javax.xml.namespace.QName
导入在抱怨。通过 "Open Type" 对话框,我发现它是通过 eureka 客户端从 stax-api
中拉取的。这为我解决了:
<exclusion>
<groupId>stax</groupId>
<artifactId>stax-api</artifactId>
</exclusion>
感谢您提供这条线索。我无法确定 org.w3c.dom.Document 的冲突引用来自何处。通过这种方式在 Eclipse 2020-12 中轻松找到它:在 Eclipse 标记的导入语句中选择 org.w3c.dom.Document,右键单击并选择 Open Type Hierarchy,在 Type Hierarchy 对话框中右键单击顶部的 Document 并选择 Implementors > 工作区显示工作区中所有项目中的所有 JAR,这些 JAR 正在引入 org.w3c.dom.Document(或您选择的可从多个模块访问的任何类型 – MikeOnline 昨天
按照前面一篇帖子中的上述说明帮助我们解决了问题。
我们所做的是将 Document 替换为 GenericDocument 并将 Element 替换为 batik 中的 GenericElement - 编译错误消失了 - 现在我们只需要测试以确保实现与我们在 java 下的内容相匹配 8. 谢谢 MikeOnline
我正在 Eclipse 中开发 Maven project(分支 platform-bom_brussels-sr7)。当我最近尝试将项目的 Java Build Path 切换到 JDK 10 时,Eclipse build 再也找不到 classes such as javax.xml.xpath.XPath
, org.w3c.dom.Document
,或 org.xml.sax.SAXException
。似乎只有 XML 相关的 classes 受到影响,主要来自 Maven 依赖项 xml-apis-1.4.01
.
尝试从 Eclipse 构建 Maven 没有错误。按住 Ctrl-左键单击其中一个据称缺失的 classes 会找到 class 并在 Eclipse 编辑器中将其打开。似乎只有 Eclipse 构建受到影响。
我尝试了几件事,但 none 有所帮助。我试过了:
- 清理项目
- 不同的 Eclipse 版本:氧气和光子。
- 运行 Eclipse 自身 JDK 8 和 JDK 10。
- 正在更改项目的编译器合规性级别。它在 JDK 8 构建路径下以合规级别 8 和 10 构建,并且在构建路径中使用 JDK 10 时都失败。
jdk 9+ 带来了与拼图项目相关的变化。 JDK 被分解成各种模块,一些模块,javaee,jaxb 和 xml 相关,默认情况下不再加载。您应该将它们直接添加到您的 Maven 构建中,而不是期望它们位于 jre 类路径中。看到这个
这似乎被报告为 Eclipse Bug 536928。也许如果每个人都去投票,他们会提高优先级。
这更像是一种解决方法,但根据我的经验,可以通过转到 "Java Build Path"、"Order and Export" 选项卡并将 "Maven Dependencies" 发送到底部(所以它在 "JRE System Library" 下方)。
在 Eclipse 4.8.0 和 JDK 10 下看到了非常相似的东西。例如
import org.w3c.dom.Element;
无法在 Eclipse 中编译:The import org.w3c.dom.Element cannot be resolved
即便如此,在该导入上按 F3(打开声明),Eclipse 仍能够打开接口定义 - 在本例中为 xml-apis-1.4.01.jar
.
与此同时,直接从 Maven 构建工作正常。
在这种情况下,修复是从 pom.xml
:
<dependency>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
<version>1.4.01</version>
</dependency>
然后 Eclipse 中的编译错误消失了。按照F3再次显示Element
界面——现在在java.xml
模块下,在项目下的JRE系统库下。 Maven 构建也保持良好。
这感觉像是 Eclipse 解决它在 JDK 模块和相关 .jar 文件中发现的 class 的问题。
有趣的是,在单独的环境中,这次在 Eclipse 4.9.0 和 JDK 11 下,一切都很好,有或没有 xml-apis:1.4.01
依赖项。
我假设正在从Java 1.8 迁移的项目仍然没有module-info.java
。这意味着您正在 "unnamed module".
未命名模块中的代码 "reads" 所有可观察的命名和未命名模块,特别是它从 JRE 系统库中读取模块 "java.xml"。此模块导出包,如 java.xml.xpath
.
此外,您在类路径上有 xml-apis.java
,它提供了另一组同名包(java.xml.xpath
和朋友)。这些据说与未命名模块相关联,就像您自己的代码一样。
这种情况违反了"unique visibility"中定义的要求JLS §7.4.3 (last paragraph). In particular every qualified type name Q.Id (JSL §6.5.5.2)要求其前缀Q是唯一可见的包(我无视为简单起见,嵌套类型的情况)。因此:该程序是非法的,必须被编译器拒绝。
这留给我们一个问题和两个解决方案:
(1)问题:javac为什么接受程序?
(2)解决方案:如果你在项目中添加module-info.java
,你可以通过requires来控制你的项目读取哪个模块,requires java.xml;
或者requires xml.apis;
(其中 "xml.apis" 是“xml-apis-1.4.01.jar”的自动模块名称)。
(3) 解决方案:如果不将您的项目转换为模块,您仍然可以通过从可观察模块集中排除 java.xml
来避免冲突。在命令行上,这将使用 --limit-modules
完成。 Eclipse 中的等效项是 "Modularity Details" dialog, see also the JDT 4.8 New&Noteworthy(查找 Contents 选项卡)。由于 java.xml
是通过许多其他默认可观察模块隐式需要的,因此将 java.base
以外的所有内容从右 ("Explicitly included modules") 推到左 ([=70) 可能是个好主意=])(并有选择地重新添加项目需要的那些模块)。
PS:Eclipse 仍然没有提供理想的错误消息,而不是 "cannot be resolved" 它实际上应该说:“包 javax.xml.xpath 可以从多个模块访问: javax.xml、<未命名>。
PPS:也很奇怪:为什么更改类路径上 JRE 和 jar 之间的顺序(这种顺序不是 javac 或 JEP 261 支持的概念)会改变编译器的行为。
编辑:
- 亚历克斯·巴克利 confirmed that the given situation is illegal, despite what javac says. Bug against javac has been raised as JDK-8215739。此错误已在 Java 12 发布前几个月得到确认。截至 2019 年 6 月,已决定 Java 13 也将在没有修复的情况下发布。 Java 14 也是如此。该错误暂时安排在 Java 15,但该计划已于 2020-04-20 取消。
- Eclipse 报错信息has been improved提一下真正的问题。
- 在 Eclipse 2019-06 中,用于解决方案 (3) 的 UI 已 revamped. Up-to-date documentation can be found in the online help。
这里发生了什么 你有一个像 import org.w3c.dom.*
这样的通配符导入,说明你想从包 org.w3c.dom
导入所有 classes .现在,如果第二个来源提供的 org.w3c.dom
中至少有一个 class,则 Java 不能启动(正如
(顺便说一下,消息“...无法解析”被更准确的错误消息“The package org.w3c.dom 可从多个模块访问:
解决这个问题
- 打开"Open Type"对话框(Ctrl+Shift+T) .
- 输入完成导入,所以
org.w3c.dom.*
或org.w3c.dom.
. - 检查整个列表是否有多个来源。此处的所有条目应仅包含类似 "jdk-11-...". 的内容
- 收集所有包含 class您有多个来源的 JAR。
- 从
pom.xml
打开 "Dependency Hirarchy" 选项卡。 - 搜索 JAR 文件。
- 添加排除项(右键单击或手动编辑
pom.xml
)。
例子
我的 pom.xml
:
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>findbugs</artifactId>
<version>${findbugs.version}</version>
</dependency>
Findbugs 有两个需要排除的依赖项:
<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>
在我的例子中,问题是 xercesImpl : 2.10.0
是一个(暂时的)依赖。这个 jar 包 org.w3c.dom.html.HTMLDOMImplementation
.
据我了解,org.w3c.dom
包随后可从两个模块获得,导致构建失败。
如果其中一个依赖项(直接或瞬态)在 java.xml module 导出的 25 个包之一中具有 类,您的构建将失败。
在 Maven 中排除 xercesImpl(以及下面列出的违规者)为我解决了这个问题:
<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>
感谢 Rune Flobakk 在这里给出提示:https://bugs.eclipse.org/bugs/show_bug.cgi?id=536928#c73
其他违规者:
batik-ext : 1.9
(捆绑组织。w3c.dom.Window)xom : 1.2.5
(捆绑组织。w3c.dom.UserDataHandler)stax-api : 1.0.2
(捆绑包 javax.xml.stream.EventFilter)xml-apis : 1.4.01
(捆绑组织。w3c.dom.Document)xml-beans : 2.3.0
(捆绑组织。w3c.dom.TypeInfo)
虽然 Stephan Herrmann 的回答是正确的,但我会 post 我的错误以及我是如何解决它的,如果它可以帮助其他人的话。我有错误 The package javax.xml.namespace is accessible from more than one module: <unnamed>, java.xml
并且在检查 class 错误之后,是 javax.xml.namespace.QName
导入在抱怨。通过 "Open Type" 对话框,我发现它是通过 eureka 客户端从 stax-api
中拉取的。这为我解决了:
<exclusion>
<groupId>stax</groupId>
<artifactId>stax-api</artifactId>
</exclusion>
感谢您提供这条线索。我无法确定 org.w3c.dom.Document 的冲突引用来自何处。通过这种方式在 Eclipse 2020-12 中轻松找到它:在 Eclipse 标记的导入语句中选择 org.w3c.dom.Document,右键单击并选择 Open Type Hierarchy,在 Type Hierarchy 对话框中右键单击顶部的 Document 并选择 Implementors > 工作区显示工作区中所有项目中的所有 JAR,这些 JAR 正在引入 org.w3c.dom.Document(或您选择的可从多个模块访问的任何类型 – MikeOnline 昨天
按照前面一篇帖子中的上述说明帮助我们解决了问题。 我们所做的是将 Document 替换为 GenericDocument 并将 Element 替换为 batik 中的 GenericElement - 编译错误消失了 - 现在我们只需要测试以确保实现与我们在 java 下的内容相匹配 8. 谢谢 MikeOnline