当引用简单的.jar文件时,Eclipse显示一个错误,声明:
可以从多个模块访问包java.awt:
例如,当.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
(不需要文件)的类路径中将导致出现错误。我使用的是JDK 10/12(两者都不起作用)。将编译器遵从性设置为1.8
会使整个过程再次正常工作。在另一台安装了Eclipse 2018-09
的机器上,这可以在编译器遵从性设置为10
的情况下运行。
我使用的是Eclipse 2019-03
,在(用于测试目的)新安装的Eclipse 2018-09
上运行良好。为什么?
编辑2020年6月(解决方案)
正如答案正确指出的那样,这是Java很久以前就内置的限制,直到最近才被强加给我们。我是在将一个有数十个依赖项的大项目迁移到Maven时接触到它的。大约2000年左右就有了图书馆!有“元库”,它由打包在一起的几个库组成。因此,除了确定仍然需要什么(与其余的一起扔进垃圾桶!)、更新违反规则的库或寻找替代库之外,没有其他方法。这花了我很多很多小时。
最后,它成功了,我们有了一个很好的Maven项目要处理。
4条答案
按热度按时间izkcnapc1#
这是由引起的**
Classpath上的JAR,它包含系统库中也存在的包**
java.awt
**,但在Java Platform Module System (JPMS)中,不允许在多个模块中使用相同的包。如果使用Modulepath和Classpath,则Classpath上的所有内容都作为
<unnamed>
模块处理(在您的例子中,包java.awt
存在于系统模块java.desktop
中,也通过模块<unnamed>
中的Classpath上的JAR)。由于无法将JRE系统库从模块路径移到类路径(请参阅this answer by Stephan Herrmann for details),因此您只有以下选项:
将编译器合规性设置为1.8(正如您已经提到的)
重建JAR以避免JAR内部的Java系统库包名称**(如果使用反射,可能需要额外修改代码):
如果您有源代码,请更改包名称(例如,将包和子包
java
更改为java_util
,将javax
更改为javax_util
)并重新创建JAR如果只有
.class
文件,则必须先反编译.class
文件2exbekwf2#
因为我打赌很多人都会在模块化Java中遇到这个问题,所以我会提供帮助并给出真正的答案。
在以下情况下发生此错误
如果您的项目已经将源代码兼容性设置为类似于Java 12,它将开始执行Java中一直存在的规则:
“不要在您自己的代码中使用属于JDK的包。”
不幸的是,多年来,许多开发人员和供应商都这样做了。我不能再那样做了。
如果您将项目设置为与Java 12源代码兼容,那么Eclipse会添加JDK模块,其中包含所有内容“java.”和“javax.”,甚至“jdk.”、“org.w3c..”。这些包可能正在由您的依赖项或它们的传递依赖项使用。
如何修复
您需要:
或者,您可以获取该依赖项的源代码(如果可用),并使用更改后的包重新构建JAR。否则,您必须消除这种依赖,并找到该技术的替代品。疼吧?
如果它是一种可传递的依赖关系,您通常可以将其排除在外。下面是一个基于Gradle的项目的例子。
GradleConfig.xml:
vngu2lb83#
在我的例子中,这是因为我在POM.xml文件中包含了一个依赖项(ApacheTika)。
在该依赖项中导入时,我必须强制排除包含有错误的类的模块:
这对我来说很管用。
hiz5n14c4#
我想我对这个问题的理解可能会有用。
对于
javax.xml.stream
下的类,我得到了这个错误,因为旧的Maven项目依赖于xml-apis
、stax-api
或geronimo-stax-api
等构件。从技术上讲,问题是其他人已经说过的:这些构件在不知道Java模块的情况下公开
javax.xml.*
包(它们是后来发明的),所以包自动转到未命名的模块,这与JDK最新版本中包含的相同的包相冲突,在JDK的最新版本中,这些包有自己的模块名称(因此,相同的包导致两个不同的模块,这是被禁止的。也就是说,实际的解决方案基本上是使用Maven exclusions从您的项目中移除那些依赖项,并让它改用JDK版本。如果您使用的是另一个构建系统,请使用等效项。
从理论上讲,JDK提供的这些包的最新风格可能不是向后兼容的,实际上,我怀疑这些JSR规范多年来发生了很大变化,到目前为止,我还没有看到它们的替代有任何问题。