我正在开发Eclipse中的Maven project(branch platform-bom_brussels-sr7)。当我最近尝试将项目的Java Build Path切换到JDK 10时,Eclipse构建不再能够找到诸如javax.xml.xpath.XPath
,org.w3c.dom.Document
或org.xml.sax.SAXException
之类的类。似乎只有XML相关的类受到影响,主要来自Maven依赖xml-apis-1.4.01
。
从Eclipse中尝试Maven构建工作没有错误。 Ctrl-LeftClick上一个假定缺失的类找到该类并在Eclipse编辑器中打开它。似乎只有Eclipse构建受到影响。
我尝试了几件事,但都没有帮助。我试过了:
我假设从Java 1.8迁移的项目仍然没有module-info.java
。这意味着您正在编译“未命名模块”中的代码。
未命名模块中的代码“读取”所有可观察的命名和未命名模块,特别是它从JRE系统库中读取模块“java.xml”。这个模块导出像java.xml.xpath
这样的包。
另外,你在类路径上有xml-apis.java
,它提供了另一组相同名称的包(java.xml.xpath
和friends)。据说这些与未命名的模块相关联,就像您自己的代码一样。
这种情况违反了JLS §7.4.3(最后一段)中定义的“独特可见性”的要求。特别是每个限定类型名称Q.Id(JSL §6.5.5.2)要求其前缀Q是唯一可见的包(为简单起见,我忽略了嵌套类型的情况)。 Ergo:该程序是非法的,必须被编译器拒绝。
这给我们留下了一个问题和两个解决方案:
(1)问题:为什么javac接受该计划?
(2)解决方案:如果将module-info.java
添加到项目中,则可以通过控制项目读取的模块来控制requires java.xml;
或requires xml.apis;
(其中“xml.apis”是自动模块名称“xml-apis-1.4.01”。罐)。
(3)解决方案:如果没有将项目转换为模块,您仍然可以通过从可观察模块集中排除java.xml
来避免冲突。在命令行上,这将使用--limit-modules
完成。 Eclipse中的等价物是"Modularity Details" dialog,另请参阅JDT 4.8 New&Noteworthy(查找“目录”选项卡)。由于java.xml
是通过许多其他默认可观察模块隐式需要的,因此将java.base
除外的所有内容(“明确包含的模块”)推向左边(“可用模块”)可能是一个好主意(并选择性地重新添加)您项目需要的那些模块。
PS:Eclipse仍然没有提供理想的错误消息,而不是“无法解决”它应该实际上说:“包javax.xml.xpath可以从多个模块访问:javax.xml,<unnamed>。
PPS:也很奇怪:为什么改变JRE和类路径上的jar之间的顺序(这种排序不是javac和JEP 261支持的概念)会改变编译器的行为。
编辑:
这似乎被报道为Eclipse Bug 536928。也许如果每个人都去投票,它会让他们提高优先级。
在Eclipse 4.8.0和JDK 10下看到过非常类似的东西。
import org.w3c.dom.Element;
无法在Eclipse中编译:The import org.w3c.dom.Element cannot be resolved
即便如此,在该导入上按下F3(Open Declaration),Eclipse也能够打开接口定义 - 在本例中是xml-apis-1.4.01.jar
。
同时,Maven direct的构建工作正常。
在这种情况下,修复是从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文件中找到的类一样。
有趣的是,在单独的环境中,这次是在Eclipse 4.9.0和JDK 11下,一切都很好,有或没有xml-apis:1.4.01
依赖。
jdk 9+带来了与项目拼图有关的变化。 JDK被分解为各种模块,并且默认情况下不再加载一些与javaee,jaxb和xml相关的模块。您应该直接将这些添加到您的maven构建中,而不是期望它们位于jre类路径中。看到这个SO question
这更像是一种解决方法,但根据我的经验,可以通过转到“Java Build Path”,“Order and Export”选项卡,并将“Maven Dependencies”发送到底部(因此它位于“JRE系统库”)。