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)
Starting from JaCoCo 0.8. 2, we can exclude classes and methods by annotating them with a custom annotation with the following properties: The name of the annotation should include Generated. The retention policy of annotation should be runtime or class.
Why does the coverage report not show highlighted source code? Make sure the following prerequisites are fulfilled to get source code highlighting in JaCoCo coverage reports: Class files must be compiled with debug information to contain line numbers. Source files must be properly supplied at report generation time.
JaCoCo runs as a Java agent. It's responsible for instrumenting the byte code while running the tests. JaCoCo drills into each instruction, and shows which lines are exercised during each test. It's also possible to run the JaCoCo agent in server mode.
JaCoCo is a free code coverage library for Java, which has been created by the EclEmma team based on the lessons learned from using and integration existing libraries for many years.
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.
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')
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With