Eclipse被导入混淆(“可从多个模块访问”)

2022-08-31 21:19:13

引用简单的.jar文件时,Eclipse 会显示一个错误,指出:

可以从多个模块访问java.awt包:<未命名>,java.desktop

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

最简单的示例如下:

package test;

import javax.swing.JDialog;

public class Test {
    public static void main(String[] args) {
        new JDialog();
    }
}

将.jar文件添加到仅具有文件夹结构(不需要文件)的类路径将导致出现错误。我使用的是JDK 10/12(两者都不起作用)。设置编译器合规性以使整个事情再次工作。在另一台计算机上,如果编译器合规性设置为 ,则此方法可以工作。javax/swing1.8Eclipse 2018-0910

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

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

正如答案正确指出的那样,这是很久以前Java内置的限制,直到最近才强加给我们。我在将一个包含数十个依赖项的大项目迁移到 Maven 时接触到了它。2000年左右就有图书馆!有“元库”,它由几个打包在一起的库组成。因此,除了确定仍然需要的东西(与其他内容一起放入垃圾箱!),更新违反规则的库或找到它们的替代品之外,没有其他方法。这花了我很多很多个小时。

最后它成功了,我们有一个很好的Maven项目可以使用。


答案 1

这是

  • 类路径上的 JAR,其中包含也存在于系统库中的,但java.awt
  • JRE 系统库位于模块路径

Java 平台模块系统 (JPMS) 中,不允许在多个模块中使用相同的包。如果使用模块路径类路径,则类路径上的所有内容都将作为模块进行处理(在您的情况下,包存在于系统模块中,并且还通过模块中类路径上的 JAR 存在)。<unnamed>java.awtjava.desktop<unnamed>

由于 JRE 系统库无法从模块路径移动到类路径(有关详细信息,请参阅 Stephan Herrmann 的此答案),因此您只有以下选项:

  • 将编译器合规性设置为 1.8(如前所述)
  • 重新构建 JAR 以避免 JAR 中的 Java 系统库包名称(如果使用反射,则可能需要进行其他代码更改):
    • 如果您有源代码,请更改包名称(例如,将包和子包更改为 和 更改为 ),然后重新创建 JARjavajava_utiljavaxjavax_util
    • 如果您只有文件,则必须先反编译文件.class.class

答案 2

由于我敢打赌很多人在使用模块化Java时会遇到这个问题,所以我会提供帮助并给出真正的答案。

此错误发生在以下情况下

  • 您在项目中具有依赖项
  • 包含代码
  • 使用软件包
  • 也在模块中
  • 被项目引用

如果您的项目已将源兼容性设置为类似 Java 12 的内容,它将开始强制执行 Java 中一直存在的规则:

“不要在自己的代码中使用属于 JDK 的包。

不幸的是,多年来,许多开发人员和供应商都这样做了。不能再这样做了。

如果您将项目设置为Java 12源代码兼容性,Eclipse将添加JDK模块,其中包括所有内容“java.*”和“javax.*”,甚至“jdk.*”,“org.w3c.*”。这些包可能正由依赖项或其传递依赖项使用。

如何修复

您需要:

  • 看看它抱怨哪个包裹
  • ,然后展开包资源管理器中的“项目和外部依赖项”节点。
  • 找出哪个依赖项正在使用该包。
  • 然后,您可以简单地从项目中排除该依赖项。

或者,您可以获取该依赖项的源(如果可用),并使用更改的包重新构建 jar。否则,您必须删除该依赖项并找到该技术的替代品。痛吧?

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

GradleConfig.xml

configurations {
   all*.exclude group: 'xml-apis'
}

推荐