JaCoCo Невозможно добавить другой класс с тем же именем: org/hamcrest/BaseDescription

Привет, я сталкиваюсь со следующим исключением при запуске покрытия JaCoCo:

    <plugin>
        <groupId>org.jacoco</groupId>
        <artifactId>jacoco-maven-plugin</artifactId>
        <version>0.5.8.201207111220</version>
        <executions>
            <execution>
                <goals>
                    <goal>prepare-agent</goal>
                </goals>
            </execution>
            <execution>
                <id>report</id>
                <phase>prepare-package</phase>
                <goals>
                    <goal>report</goal>
                </goals>
            </execution>
        </executions>
    </plugin>

Error while creating report: Can't add different class with same name: org/hamcrest/BaseDescription
java.lang.IllegalStateException: Can't add different class with same name: org/hamcrest/BaseDescription
    at org.jacoco.core.analysis.CoverageBuilder.visitCoverage(CoverageBuilder.java:89)
    at org.jacoco.core.analysis.Analyzer$1.visitEnd(Analyzer.java:79)
    at org.objectweb.asm.ClassAdapter.visitEnd(Unknown Source)
    at org.jacoco.core.internal.flow.ClassProbesAdapter.visitEnd(ClassProbesAdapter.java:128)
    at org.objectweb.asm.ClassReader.accept(Unknown Source)
    at org.objectweb.asm.ClassReader.accept(Unknown Source)
    at org.jacoco.core.analysis.Analyzer.analyzeClass(Analyzer.java:94)
    at org.jacoco.core.analysis.Analyzer.analyzeClass(Analyzer.java:115)
    at org.jacoco.core.analysis.Analyzer.analyzeAll(Analyzer.java:155)
    at org.jacoco.core.analysis.Analyzer.analyzeArchive(Analyzer.java:135)
    at org.jacoco.core.analysis.Analyzer.analyzeAll(Analyzer.java:158)
    at org.jacoco.core.analysis.Analyzer.analyzeAll(Analyzer.java:183)
    at org.jacoco.maven.ReportMojo.createBundle(ReportMojo.java:280)
    at org.jacoco.maven.ReportMojo.createReport(ReportMojo.java:256)
    at org.jacoco.maven.ReportMojo.executeReport(ReportMojo.java:230)
    at org.jacoco.maven.ReportMojo.execute(ReportMojo.java:208)
    at org.apache.maven.plugin.DefaultPluginManager.executeMojo(DefaultPluginManager.java:490)
    at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoals(DefaultLifecycleExecutor.java:694)
    at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalWithLifecycle(DefaultLifecycleExecutor.java:556)
    at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoal(DefaultLifecycleExecutor.java:535)
    at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalAndHandleFailures(DefaultLifecycleExecutor.java:387)
    at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeTaskSegments(DefaultLifecycleExecutor.java:348)
    at org.apache.maven.lifecycle.DefaultLifecycleExecutor.execute(DefaultLifecycleExecutor.java:180)
    at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:328)
    at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:138)
    at org.apache.maven.cli.MavenCli.main(MavenCli.java:362)
    at org.apache.maven.cli.compat.CompatibleMain.main(CompatibleMain.java:60)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.codehaus.classworlds.Launcher.launchEnhanced(Launcher.java:315)
    at org.codehaus.classworlds.Launcher.launch(Launcher.java:255)
    at org.codehaus.classworlds.Launcher.mainWithExitCode(Launcher.java:430)
    at org.codehaus.classworlds.Launcher.main(Launcher.java:375)

person DarVar    schedule 26.07.2012    source источник
comment
Примерно в 2018 году, и это становится действительно актуальным благодаря многорелизным JAR-файлам JEP-238.   -  person earcam    schedule 28.06.2018
comment
Посмотрите на stackoverflow.com/a/62038840/418599 мое решение.   -  person Antonio Petricca    schedule 27.05.2020


Ответы (5)


Есть два способа избежать этого:

1) Переименуйте один из дубликатов: я довольно часто сталкивался с этой проблемой, когда дело доходит до проектов maven. Даже если эти два класса находятся в двух разных модулях, иметь одинаковые имена для двух разных классов не очень хорошая идея.

2) Исключите один из них: см. в этой ветке SO для получения дополнительной информации.

person rb512    schedule 22.08.2012
comment
Верный. Еще одна область, где во время процесса компиляции, если мы используем JIBX/etc, создаются файлы динамических классов (время компиляции), для которых у нас нет действительного соответствующего исходного файла (.java/.groovy и т. д.). В этом случае, когда jacoco попытается сгенерировать отчет, он выдаст ту же ошибку для дубликата... В этом случае, если вы найдете какой-либо дубликат исходного файла, вы не найдете ни одного (поскольку не было исходные файлы из первых рук). Чтобы решить эту проблему, вы должны удалить все файлы классов перед запуском отчетов jacoco. - person AKS; 14.11.2015

Я согласен с rb512. Еще один случай/область, в которой может возникнуть эта ошибка, - это процесс компиляции, если мы используем JIBX/WST и т. д. или аналогичные другие шаги/процесс, которые создают файлы динамических классов (во время компиляции), т.е. для которых у нас нет действительных соответствующих исходный файл (.java/.groovy и т. д.) в рабочей области.

В этом случае ваше рабочее пространство будет иметь дополнительные файлы классов, и когда jacoco попытается сгенерировать отчет, он выдаст ту же ошибку для дублирующегося класса. Если вы обнаружите эту ошибку из-за этого случая, вам необходимо удалить все файлы классов перед запуском отчетов jacoco.

Если вы используете Gradle (для Maven сделайте то же самое в файле Maven pom .xml), см. блок doFirst ниже, который выполняет трюк.

  jacocoTestReport {
      //cleaning up the JiBx classes to jacoco will not cause problems for CareDiscovery
      doFirst {
             delete fileTree (dir: "${buildDir}/classes", include: "**/JiBX_*.class")
      }
      group = "Reporting"
      description = "Generate Jacoco coverage reports after running tests."

      executionData = fileTree(dir: 'build/jacoco', include: '**/*.exec')

      reports {
             xml{
                 enabled true
                 //Following value is a file
                 destination "${buildDir}/reports/jacoco/xml/jacoco.xml"
             }
             csv.enabled false
             html {
                 enabled true
                 //Following value is a folder
                 destination "${buildDir}/reports/jacoco/html"
             }
      }

      sourceDirectories = files(['src/java','src/main/java', 'src/main/groovy'])
      classDirectories =  files('build/classes/main')
  }
person AKS    schedule 13.11.2015
comment
Несколько лучший вариант, чем удаление повторяющихся классов, — просто удалить их из classDirectories: doFirst { classDirectories = files(classDirectories.files.collect { fileTree(dir: it, excludes: ['some/package/to/exclude/** ', 'какой-то/другой/пакет/для/исключения/**']) }) } - person Jumpy; 30.11.2016

Я столкнулся с той же проблемой, что и вы. Оказывается, у меня в папке проекта было две банки, которые делали одно и то же, хотя только одна из них находилась в пути сборки. Проверьте, есть ли в вашем коде более одной банки hamcrest.

person MisterStrickland    schedule 14.05.2016

В моем случае проблемы возникали из-за класса в артефакте Jar проекта.

    Caused by: java.io.IOException: Error while analyzing /opt/jenkins/workspace/MicroService-M_build/microservice/dev/microservice/build/gen/main/resources/uploadassets/myCustomProject.jar@org/apache/commons/beanutils/BasicDynaBean.class.
Caused by: java.lang.IllegalStateException: Can't add different class with same name: org/apache/commons/beanutils/BasicDynaBean
    at org.jacoco.core.analysis.CoverageBuilder.visitCoverage(CoverageBuilder.java:107)

Ниже приведены градации, чтобы исключить пользовательскую банку из отчета о тестировании jacoco.

jacocoTestReport {
        doFirst {
            delete fileTree (dir: "${buildDir}/gen/main/resources/uploadassets", include: "myCustomProject.jar")
        }
        reports {
            xml.enabled true
        }
    }

Это решило мою проблему.

person Sanjay Bharwani    schedule 25.01.2021

Эта проблема обычно вызывается некоторыми файлами jar или файлами проекта в папке target. Это то, что решило проблему в нашем проекте maven (см. /65885458#65885458">Ответ Санджая для Gradle):

        <plugin>
            <groupId>org.jacoco</groupId>
            <artifactId>jacoco-maven-plugin</artifactId>
            <version>0.8.7</version>
                <configuration>
                   <excludes>**/*.jar</excludes>
                </configuration>
        </plugin>

Обратите внимание, что это самое простое решение, работающее для нашего конкретного проекта. Если вам нужно сделать дополнительные исключения, оберните несколько <exclude>-команд следующим образом:

            <configuration>
                <excludes>
                    <exclude>**/*.jar</exclude>
                    <exclude>naughty-dependency/**/*.class</exclude>
                </excludes>
            </configuration>

Примечание. Этот раздел конфигурации не связывает JaCoCo с какими-либо <execution> целями намеренно. Таким образом, процесс упаковки по умолчанию не прерывается, когда JaCoCo падает, а также работает немного быстрее. Отчеты будут генерироваться только при выпуске mvn org.jacoco:jacoco-maven-plugin:prepare-agent test jacoco:report, что мы делаем, например, в нашем gitlab CI-конвейере.

person Philzen    schedule 13.05.2021