Java Eclipse被导入(可从多个模块访问)弄糊涂了

Java Eclipse被导入(可从多个模块访问)弄糊涂了,java,eclipse,jar,Java,Eclipse,Jar,引用simple.jar文件时,Eclipse显示一个错误,说明: 可以从多个模块中访问包java.awt:,java.desktop 例如,当.jar文件中包含javax.awt或javax.swing时,就会发生这种情况 最简单的例子如下: package test; import javax.swing.JDialog; public class Test { public static void main(String[] args) { new JDialo

引用simple.jar文件时,Eclipse显示一个错误,说明:

可以从多个模块中访问包java.awt:,java.desktop

例如,当.jar文件中包含
javax.awt
javax.swing
时,就会发生这种情况

最简单的例子如下:

package test;

import javax.swing.JDialog;

public class Test {
    public static void main(String[] args) {
        new JDialog();
    }
}
将.jar文件添加到仅具有文件夹结构的类路径
javax/swing
(不需要任何文件)将导致出现错误。我使用的是JDK10/12(两者都不起作用)。将编译器符合性设置为
1.8
将使整个过程再次运行。 在另一台装有
Eclipse 2018-09
的机器上,这可以在编译器符合性设置为
10
的情况下工作

我在Eclipse
2019-03
上,在一个新安装的
Eclipse 2018-09
上(出于测试目的),它工作正常。为什么?

编辑2020年6月(解决方案)

正如正确的答案所指出的,这是Java多年前就建立起来的限制,直到最近才强加给我们。我是在将一个有几十个依赖项的大型项目迁移到Maven时接触到它的。2000年左右就有图书馆了!有“元库”,由几个打包在一起的库组成。 因此,除了确定还需要什么(与其他库一起放入垃圾箱!)、更新违反规则的库或找到替换库之外,没有其他方法。这花了我很多很多小时


最后它成功了,我们有一个很好的Maven项目要处理。

这是由

  • 类路径上的JAR,其中包含
    java.awt
    ,该包也存在于系统库中,但
  • JRE系统库在模块路径上
在中,不允许在多个模块中使用同一软件包。如果使用了Modulepath和类路径,则类路径上的所有内容都将作为
模块处理(在您的情况下,包
java.awt
存在于系统模块
java.desktop
中,也通过模块
中类路径上的JAR处理)

由于JRE系统库无法从Modulepath移动到类路径(请参阅),因此您只有以下选项:

  • 将编译器符合性设置为1.8(正如您已经提到的)
  • 重建JAR避免JAR中的Java系统库包名(如果使用反射,可能需要额外的代码更改):
    • 如果您有源代码,请更改包名(例如,将包和子包
      java
      更改为
      java_-util
      ,将
      javax
      更改为
      javax_-util
      )并重新创建JAR
    • 如果只有
      .class
      文件,则必须首先反编译
      .class
      文件

因为我敢打赌,很多人会在模块化Java中遇到这个问题,所以我将提供帮助并给出真正的答案。如果项目中存在依赖项,该依赖项包含使用包的代码,而包也位于项目引用的模块中,则会发生此错误。如果您的项目已将源代码兼容性设置为类似Java12的内容,它将开始强制执行Java中一直存在的规则。“不要在自己的代码中使用属于JDK的包。”不幸的是,许多开发人员和供应商多年来都这么做了。不能再那样做了。如果您将项目设置为Java12源代码兼容性,Eclipse将添加JDK模块,其中包括所有内容“Java.”和“javax.”甚至“JDK.”、“org.w3c.”。您的依赖项或其可传递依赖项可能正在使用这些包

如何修复:您需要查看其抱怨的包,并在包资源管理器中展开“项目和外部依赖项”节点。找出使用该包的依赖项。然后,您可以简单地从项目中排除该依赖项。或者,您可以获取该依赖项的源(如果可用),并使用更改的包重新构建jar。否则,您必须删除该依赖项并找到该技术的替代品。痛啊

如果它是一个可传递的依赖项,您通常可以将其排除在外。下面是一个基于Gradle的项目的例子

configurations {
    all*.exclude group: 'xml-apis'
}
另见:我的回答:

令人失望的是,我没有看到任何编译器标志来显示jar的问题所在 偶数-Xlint:module似乎没有显示任何有用的内容,eclipse也没有对这个问题给出任何解释

相反,为了找到java.awt的来源,我一直在使用以下脚本:

mvn dependency:copy-dependencies -DincludeScope=test -DoutputDirectory=deps
for i in deps/*.jar; do if unzip -l $i| grep -q java.awt; then echo $i; fi ; done

严格地说,您不必指定范围测试,因为这是默认设置,但我将其包括在内,因为您可能希望使用
compile
而不是在我的示例中,这是因为我在POM.xml文件中包含了一个依赖项(Apache Tika)

在该依赖项处导入时,我必须强制排除包含有错误类的模块:

    <dependency>
        <groupId>org.apache.tika</groupId>
        <artifactId>tika-parsers</artifactId>
        <version>1.24.1</version>
        <exclusions>
            <exclusion>
                <groupId>xml-apis</groupId>
                <artifactId>xml-apis</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

org.apache.tika
提卡解析器
1.24.1
xml API
xml API

这对我来说很有效。

我想我对这个问题的看法可能有用

我在
javax.xml.stream
下的类中遇到了这个错误,这些类是由依赖于
xmlapi
staxapi
geronimo staxapi
等工件的旧Maven项目生成的

从技术上讲,问题是其他人已经说过的:这些工件公开了
javax.xml.*
包,而没有意识到Java模块(它们出生得更早),因此包自动转到未命名模块,这与包含在Java模块中的相同包相冲突