Maven构建 [警告] 我们有一个重复的类

33

有人知道我的Maven构建出了什么问题吗?我收到了很多重复警告。

[WARNING] We have a duplicate org/apache/commons/logging/impl/LogFactoryImpl$1.class in /home/shengjie/.m2/repository/commons-logging/commons-logging-api/1.0.4/commons-logging-api-1.0.4.jar
[WARNING] We have a duplicate org/apache/commons/logging/impl/LogFactoryImpl.class in /home/shengjie/.m2/repository/commons-logging/commons-logging-api/1.0.4/commons-logging-api-1.0.4.jar
[WARNING] We have a duplicate org/apache/commons/logging/impl/NoOpLog.class in /home/shengjie/.m2/repository/commons-logging/commons-logging-api/1.0.4/commons-logging-api-1.0.4.jar
[WARNING] We have a duplicate org/apache/commons/logging/impl/SimpleLog$1.class in /home/shengjie/.m2/repository/commons-logging/commons-logging-api/1.0.4/commons-logging-api-1.0.4.jar
[WARNING] We have a duplicate org/apache/commons/logging/impl/SimpleLog.class in /home/shengjie/.m2/repository/commons-logging/commons-logging-api/1.0.4/commons-logging-api-1.0.4.jar
[WARNING] We have a duplicate org/apache/commons/logging/impl/Jdk14Logger.class in /home/shengjie/.m2/repository/commons-logging/commons-logging-api/1.0.4/commons-logging-api-1.0.4.jar

我查看了本地的m2仓库,我在commons-logging-api jar中找到了两个类,LogFactoryImpl.class和LogFactoryImpl$1.class。这与警告中提到的所有类都是一样的。

值得一提的是,我在我的pom.xml中使用了shade插件。

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>1.4</version>
            <configuration>
                <createDependencyReducedPom>true</createDependencyReducedPom>
                <filters>
                    <filter>
                        <artifact>*:*</artifact>
                        <excludes>
                            <exclude>META-INF/*.SF</exclude>
                            <exclude>META-INF/*.DSA</exclude>
                            <exclude>META-INF/*.RSA</exclude>
                        </excludes>
                    </filter>
                </filters>
            </configuration>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <transformers>
                            <transformer
                                implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
                            <transformer
                                implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                <mainClass>com.~~~~black out my own main class here~~~~~</mainClass>
                            </transformer>
                        </transformers>
                    </configuration>
                </execution>
            </executions>
        </plugin>

我注意到依赖树看起来像下面这样

[INFO] +- org.apache.cxf:cxf-bundle-jaxrs:jar:2.5.1:compile
[INFO] |  \- commons-logging:commons-logging:jar:1.1.1:compile
[INFO] \- org.apache.hadoop.hive:hive-jdbc:jar:0.7.1-cdh3u3:compile
[INFO]    \- org.apache.hadoop.hive:hive-common:jar:0.7.1-cdh3u3:compile
[INFO]       \- commons-logging:commons-logging-api:jar:1.0.4:compile

同时commons-logging.jar和commons-logging-api.jar都有org/apache/commons/logging/LogFactory.class。

某种程度上,Shad插件试图将它们压缩到一个大的可执行文件中。然后警告就会出现。虽然有人说这是可以忽略的警告,但我有点担心,如果有两个重复的具有相同名称的类,应用程序如何知道应使用哪个确切的类呢?


1
LogFactoryImpl.class和LogFactoryImpl$1.class,名称中带有$1的类是LogFactoryImpl内部的本地类。 - khmarbaise
8个回答

14

请查看Maven文档中的“Dependency Exclusions”部分。

在您提供的示例中,我将从org.apache.hadoop.hive:hive-common:jar:0.7.1-cdh3u3:compile中排除commons-logging:commons-logging-api:jar:1.0.4:compile依赖项。在您的pom.xml文件中:

    <dependency>
        <groupId>org.apache.hadoop.hive</groupId>
        <artifactId>hive-common:jar</artifactId>
        <version>0.7.1-cdh3u3</version>
        <exclusions>
            <exclusion>
                <groupId>commons-logging</groupId>
                <artifactId>commons-logging-api</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

非常感谢,这很有道理。那么,最好的方法是如何管理这样的依赖关系呢?比如说,你有projectA.jar、projectB.jar,它们在不同版本中具有相同的依赖项,例如dependency.1.0、dependency.2.0。仅使用其中一个存在风险。有没有一种方法让ProjectA继续使用depdency.1.0,而ProjectB仍然使用dependency.2.0呢? - Shengjie
1
不可能的,没有办法(也许在OSGI方面我不是专家,但)在这种情况下,类加载器会选择要使用的类(取决于操作系统、JVM等等,通常使用类路径中引用的第一个jar文件)。你最好的选择是使用最新版本(排除其他版本),希望它是向后兼容的......但这比让类加载器为你选择要好。 - ndeverge

14
您可能已经遇到了maven-shader-plugin的限制。它替换了由maven-jar-plugin创建的默认jar构件。这在干净构建时可以正常工作,但在不重新生成jar文件的重建上,着色器再次运行在上次创建的jar文件上,该文件已包含所有类依赖项的副本。这会产生许多关于重复项的警告。
截至maven-shader-plugin 2.0版本,此问题仍未得到解决: https://issues.apache.org/jira/browse/MSHADE-126 一种解决方法是在pom.xml中显式添加maven-jar-plugin,并添加配置设置<forceCreation>true</forceCreation>

1
这就是导致问题的原因。您可以通过按照此处的解决方案解决它:https://dev59.com/5Wox5IYBdhLWcg3w74q3 - stantonk

5
在我的情况下,我的父POM包含commons-beanutils,而我的子模块(我唯一想编译的内容)包含commons-io。shade插件因为commons-io和commons-beansutil共享一些公共类而抱怨重复。需要注意的是,即使不需要beansutiul并且未使用,它也被包含了。
我通过添加以下配置来最小化jar文件来解决这个问题:
<minimizeJar>true</minimizeJar>

现在,shade插件不会添加未使用的资源。
警告已经消失。

3
在大多数情况下,上述关于审核依赖树和排除依赖项的内容都是正确的,但在我的情况下(我没有重叠的依赖项),初步的“clean”操作有所帮助(尽管我不知道原因):
mvn clean package

2

您可以使用shade插件下面的以下标签来排除您不想要的jar包(那些会出现重复警告的jar包) -

<configuration>
    <artifactSet>
        <excludes>
            <exclude>commons-logging:commons-logging</exclude>
        </excludes>
    </artifactSet>
    <minimizeJar>true</minimizeJar>
</configuration>

更多详细信息请访问http://maven.apache.org/plugins/maven-shade-plugin/shade-mojo.html


0
在我的情况下,我依赖于一个还创建了一个阴影jar的包。
阴影jar是用于部署而不是安装依赖项的。
在依赖项的构建过程中创建一个减少依赖项POM,指示Maven可以省略哪些依赖项。
在maven-shade-plugin配置中:
<configuration>
  <createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>

更多细节请参见此帖:

什么是maven-shade-plugin,为什么要重新定位Java包?

Maven给出的错误信息:

警告:x.jar,y.jar包含重叠的类


0

当我更新了父项目的依赖关系时,我在eclipse中看到了这种情况发生。

我删除了目标目录中的所有文件,问题得到了解决。


-3

你的pom文件中存在包含重复类的依赖项,但是如果没有适当的pom文件,我无法对此发表意见。


添加了更多信息,您能再看一下吗?谢谢。 - Shengjie
你有检查过哪个依赖项包含了重复的类吗?根据你的输出,commons-logging-api-1.0.4.jar 似乎来自于使用不同的 API 版本(重复),或者你正在使用其他的日志提供程序(slf4j?)。 - khmarbaise

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接