42

Hi I'm hitting the following exception when running a JaCoCo coverage:

    <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)
mkobit
  • 43,979
  • 12
  • 156
  • 150
DarVar
  • 16,882
  • 29
  • 97
  • 146

5 Answers5

14

There are two ways to avoid this:

1)Rename one of the duplicates: I've seen this problem quite often when it comes to maven projects. Even if those two classes are in two different modules, having same names for two different classes is not really a good idea.

2)Exclude one of them: Refer this SO thread for more information.

Community
  • 1
  • 1
rb512
  • 6,880
  • 3
  • 36
  • 55
  • 1
    Correct. One more area is where during compilation process if we are using JIBX/etc which creates dynamic class files (compile time) for which we don't have a valid corresponding source file (.java/.groovy etc). In that case, when jacoco will try to generate the report, it'll error out with the same error for duplicate ... In that case if you find for any duplicate source file, you won't find any (as there were no source files on the first hand). To solve it, you have to remove any class files before running jacoco reports. – AKS Nov 13 '15 at 21:54
4

I agree with rb512. One more case/area where this error can come is, during compilation process if we are using JIBX/WST etc or similar other steps/process which creates dynamic class files (at compile time) i.e. for which we don't have any valid corresponding source file (.java/.groovy etc) in the workspace.

In that's case, your workspace will have extra class file(s) and when jacoco will try to generate the report, it'll error out with the same error for a duplicate class. If you find this error due to this case, you have to remove any class files before running jacoco reports

If you are using Gradle (for Maven, do the same in Maven pom .xml file), see the doFirst block below which is doing the trick.

  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')
  }
AKS
  • 16,482
  • 43
  • 166
  • 258
  • A slightly better option than deleting the duplicate classes is to just remove them from the classDirectories: doFirst { classDirectories = files(classDirectories.files.collect { fileTree(dir: it, excludes: ['some/package/to/exclude/**', 'some/other/package/to/exclude/**']) }) } – Jumpy Nov 30 '16 at 16:55
4

Certain jars or project files in the target-folder usually cause this issue. This is what solved the problem in our maven project (see Sanjay's answer for gradle):

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

Note that this is the simplest solution working for our specific project. If you need to make additional exclusions, wrap multiple <exclude>-commands as follows:

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

N.B. this configuration section doesn't attach JaCoCo to any <execution>-goals on purpose. This way the default packaging process won't break when JaCoCo falls over and also runs slightly faster. Reports will only be generated when issuing mvn org.jacoco:jacoco-maven-plugin:prepare-agent test jacoco:report, which we do in our gitlab CI-pipeline for instance.

Philzen
  • 3,945
  • 30
  • 46
1

I hit the same issue as you. It turns out I had two jars in my project folder that did the same thing, even though only one of them was in the build path. Check if you have more than one hamcrest jar in your code.

MisterStrickland
  • 947
  • 1
  • 15
  • 35
1

In my case the issues was happening due to class in project Jar artefact.

    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)

Below is the gradle taks to exclude the custom jar from jacoco test report

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

This solved my issue.

Sanjay Bharwani
  • 3,317
  • 34
  • 31