JaCoCo and MR Jars
Asked Answered
T

3

5

There is an issue with JaCoCo and the MultiRelease JAR files. Since the same class name exist on two places, JaCoCo complains:

Caused by: java.lang.IllegalStateException: Can't add different class with same name: jodd/core/JavaBridge
        at org.jacoco.core.analysis.CoverageBuilder.visitCoverage(CoverageBuilder.java:107)
        at org.jacoco.core.analysis.Analyzer$1.visitEnd(Analyzer.java:96)

How we can tell JaCoCo (in Gradle) to skip the classes from META-INF path? OR to behave like it should (use correct class and ignoring other versions), depending on JVM version?

Tortuosity answered 6/12, 2017 at 0:6 Comment(0)
T
3

As explained by @nullpointer, JaCoCo doesn't support Multi-Release JAR Files.

My workaround is to ignore the versions classes. I was not able to ignore just the class by explicitly set its name, it looks like JaCoCo is scanning all of them and then only later applies the filters for exclusion (but maybe I am wrong).

Therefore, the only way to remove versions classes was to exclude all resources - since they are not used anyway. Like this:

task codeCoverage(type: JacocoReport) {
    executionData fileTree("${buildDir}/jacoco/").include("*.exec")

    //sourceSets it.sourceSets.main  <--- REPLACED WITH FOLLOWING LINES!!!
    sourceDirectories = it.sourceSets.main.java
    classDirectories = it.sourceSets.main.output.classesDirs

    reports {
        xml.enabled true
        html.enabled true
    }
}

So I changed this:

sourceSets it.sourceSets.main

to this:

sourceDirectories = it.sourceSets.main.java
classDirectories = it.sourceSets.main.output.classesDirs

The difference here that we explicitly state: sourceSets.main.output.classesDirs which excludes resources.

Source

Tortuosity answered 6/12, 2017 at 11:47 Comment(0)
M
2

I had the same problem on Jacoco 0.8.8 (I guess they haven't fixed it yet). But I use maven, not gradle, so even though the accepted answer is correct, it was very hard for me to follow. First, files should be excluded in the report goal, not in the prepare-agent goal. That was not at all obvious to me and took careful reading of the maven jacoco help which can be seen using the following command

mvn help:describe -Dplugin=org.jacoco:jacoco-maven-plugin -Ddetail

Second, it wasn't obvious to me whether the exclude value was a path or a package reference and, if a path, what kind of path. By experimenting I found it's a path relative to the target/classes folder. Also note that foo/* excludes all the files in the foo folder. To exclude all files recursively under foo use foo/**/*. Based on all that this is what my unit test report goal looks like.

<!-- Use unit test coverage data to generate report -->
<execution>
    <id>after-unit-tests-generate-report</id>
    <phase>test</phase>
    <goals>
        <goal>report</goal>
    </goals>
    <configuration>
        <!-- Exclude alternate versions for multi-release modules-->
        <excludes>
            <exclude>META-INF/**/*</exclude>
        </excludes>
        <dataFile>${jacoco.data.file.ut}</dataFile>
        <outputDirectory>${jacoco.report.folder.ut}</outputDirectory>
    </configuration>
</execution>

That code excludes all the files under target/classes/META-INF. In other words, all the other versions besides the base. I was worried that my tests use Java 11 but my base is Java 8, but my coverage results seem correct.

Note the use of properties jacoco.data.file.ut and jacoco.report.folder.ut. Those are defined earlier in my pom file and otherwise are not relevant to this discussion. Also note, this is defined in the parent pom of a project with lots of child modules. Even though it is not inside a pluginManagement tag (only a plugins tag) it still applies for all the children.

Mention answered 10/6, 2022 at 21:4 Comment(0)
D
1

JaCoCo doesn't yet provide support for Java 9 Multi-Release JAR Files.

This seems to be in their plans though as tracked at jacoco/issues#407.

Dannettedanni answered 6/12, 2017 at 1:29 Comment(2)
@Tortuosity How about skipping(exclusion) the META-INF/*.class directory to start with?Dannettedanni
trying that :) the thing is, it sounds easy, but it is quite complex (or i don't see it atm). the analysis engine takes all files first, before actual reporting, hence the issue. so far I am trying to remove all resources folder(s) as they are not needed for the reports.Tortuosity

© 2022 - 2024 — McMap. All rights reserved.