Maven build [ПРЕДУПРЕЖДЕНИЕ] у нас есть дубликат класса

Кто-нибудь знает, что случилось с моей сборкой 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. То же, что и все классы, упомянутые в предупреждениях.

Стоит упомянуть, что я использую плагин Shade в моем pom.xml.

        <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 пытается сжать их в большую толстую банку в конце. тогда появляется предупреждение. Было сказано, что это игнорируемое предупреждение. Но я немного волнуюсь, откуда приложение знает, какой именно класс следует использовать, если есть два дублированных класса с одинаковыми именами?

8 ответов

Решение

Взгляните на раздел "Исключения зависимостей" в документе Maven.

В приведенном вами примере я исключу commons-logging:commons-logging-api:jar:1.0.4:compile зависимость от org.apache.hadoop.hive:hive-common:jar:0.7.1-cdh3u3: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>

Возможно, вы также столкнулись с ограничением maven-shader-plugin. Он заменяет артефакт jar по умолчанию (созданный maven-jar-plugin). Это отлично работает при чистой сборке, но при перекомпоновке, где jar не регенерируется, шейдер снова запускается на jar, который он создал в прошлый раз, который уже содержит копии всех зависимостей класса. Это производит много предупреждений о дубликатах.

Эта проблема до сих пор не решена, поскольку в maven-shader-plugin 2.0: https://issues.apache.org/jira/browse/MSHADE-126

Одним из обходных путей является явное добавление maven-jar-plugin в ваш файл pom.xml и добавление параметра конфигурации <forceCreation>true</forceCreation>,

В моем случае мой родительский pom включал в себя commons-beanutils, а мой дочерний модуль (это единственное, что я хотел скомпилировать) включал commons-io.

Плагин shade жаловался на дубликаты, так как commons-io и commons-beansutil имеют несколько общих классов. Обратите внимание, что beansutiul был включен, хотя он не был нужен и не использовался.

Я решаю это путем минимизации фляги, добавляя это к конфигурации:

<minimizeJar>true</minimizeJar>

Теперь плагин Shade не добавляет неиспользуемые ресурсы.

Предупреждение ушло.

Все вышеизложенное (о просмотре дерева зависимостей и исключении) в большинстве случаев является правильным, но в моем случае (у меня не было перекрытия в моих зависимостях) предварительно clean помог (хотя не знаю почему):

mvn clean package

Вы можете исключить банку, которая вам не нужна (те, которые выдают двойные предупреждения, используя следующие теги в плагине тени -

    <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

В моем случае я полагался на упаковку, которая также создает затененную банку.

Затененные банки предназначены для развертывания, а не для установки в качестве зависимости.

Создание сокращенного POM для зависимости во время процесса построения зависимости указывает maven, какие зависимости могут быть опущены.

В конфигурации maven-shade-plugin:

<configuration>
  <createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>

Для более подробной информации смотрите этот пост:

Для чего используется плагин maven-shade-plugin и почему вы хотите переместить java-пакеты?

Ошибка, которую я получал от Maven:

ВНИМАНИЕ: x.jar, y.jar содержат перекрывающиеся классы

Я видел, что это произошло в затмении, когда я обновил зависимости моего родительского проекта.

Я удалил все файлы в моей целевой директории, и это устранило проблемы.

У вас есть зависимости в вашем pom, которые содержат повторяющиеся классы, но без соответствующего pom я не мог бы сказать об этом ни слова.

Другие вопросы по тегам