java.lang.LinkageError: loader 'bootstrap' attempted duplicate class definition for java.lang.$JaCoCo with Java11 and Jacoco 0.8.5
Asked Answered
C

1

6

I am getting following error while running a test project in Jenkins

Caused by: java.lang.LinkageError: loader 'bootstrap' attempted duplicate class definition for java.lang.$JaCoCo. (java.lang.$JaCoCo is in module java.base of loader 'bootstrap')

Jacoco is defined in the parent pom and the current test pom with different goals.

parent-pom.xml

<build>
  <plugins>
    <plugin>
      <groupId>org.jacoco</groupId>
      <artifactId>jacoco-maven-plugin</artifactId>
      <version>0.8.5</version>
      <dependencies>
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.13</version>
        </dependency>
      </dependencies>
      <executions>
        <execution>
          <id>validate-headless</id>
          <phase>validate</phase>
          <goals>
            <goal>prepare-agent</goal>
          </goals>
          <configuration>
            <skip>true</skip>
            <propertyName>failsafe.argLine</propertyName>
          </configuration>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

test-project-pom.xml

<properties>
  <maven.repo.local>${user.home}/.m2/repository</maven.repo.local>
  <itCoverageAgent>-javaagent:${maven.repo.local}/org/jacoco/org.jacoco.agent/0.8.5/org.jacoco.agent-0.8.5-runtime.jar=destfile=${basedir}/target/jacoco-it.exec</itCoverageAgent>
</properties>

<build>
  <plugins>
    <plugin>
      <artifactId>maven-failsafe-plugin</artifactId>
      <configuration>
        <argLine>${failsafe.argLine} ${itCoverageAgent}</argLine>
        <testFailureIgnore>true</testFailureIgnore>
        <reuseForks>true</reuseForks>
      </configuration>
    </plugin>
  </plugins>
</build>

<profiles>
  <profile>
    <id>coverage</id>
    <build>
      <plugins>
        <plugin>
          <groupId>org.jacoco</groupId>
          <artifactId>jacoco-maven-plugin</artifactId>
          <version>0.8.5</version>
          <executions>
            <execution>
              <id>prepare-agent-unit</id>
              <goals>
                <goal>prepare-agent</goal>
              </goals>
            </execution>
            <execution>
              <id>prepare-agent-integration</id>
              <goals>
                <goal>prepare-agent-integration</goal>
              </goals>
              <configuration>
                <propertyName>itCoverageAgent</propertyName>
              </configuration>
            </execution>
            <execution>
              <id>report-unit</id>
              <goals>
                <goal>report</goal>
              </goals>
            </execution>
            <execution>
              <id>report-integration</id>
              <goals>
                <goal>report-integration</goal>
              </goals>
            </execution>
          </executions>
        </plugin>
      </plugins>
    </build>
  </profile>
</profiles>

If ${itCoverageAgent} is removed from <argLine> in test-project-pom.xml it works fine. How do we execute different goals from parent-pom and test-project-pom for the same version of Jacoco ?

Caddis answered 21/5, 2022 at 9:53 Comment(0)
B
3

When you fail at runtime with a java.lang.LinkageError after building with Maven, it's usually an indication that different versions of the same dependency are getting loaded into the JVM. This type of conflict can arise when one of the other dependency entries in your POM has a transitive dependency on a different version of the same Java library or Java class.

You can use the Maven Dependency Plugin to generate a detailed outline of your dependencies, along with all of their transitive dependencies, by running the following command at the root of your project:

mvn dependency:tree

The output is extremely helpful, but it is an exhaustive dependency list, and can sometimes end up being too much of a good thing. If that's true for your project, there is an includes option that may be used to filter the output so that it's focused on a specific dependency or group of dependencies. As an example, you might use it is follows, with an asterisk ('*') wildcard to focus on just Jacoco dependencies:

mvn dependency:tree -Dincludes=org.jacoco.*

The includes option allows multiple filter clauses, separated by a comma (','), and also supports multiple levels of Maven dependency filtering, using the following format structure:

[groupId]:[artifactId]:[type]:[version]

You can find more reference material and documentation on the Maven Dependency Plugin's Filtering the dependency tree web page.

If you do find that you have a transitive dependency that's causing a conflict, the issue can usually be resolved by adding an <exclusions> entry within the definition of the dependency that's causing the problem:

<dependency>
  <groupId>org.open.source.library</groupId>
  <artifactId>problematic-artifact</artifactId>
  <scope>provided</scope>
  <exclusions>
    <exclusion>
      <groupId>org.jacoco</groupId>
      <artifactId>conflicting-transitive-artifact</artifactId>
    </exclusion>
  </exclusions>
</dependency>

This maintains your desired dependency but excludes resolution of the transitive dependency that is creating the conflict, and will resolve the runtime linkage error.


Actually, I don't believe your root problem is a dependency version mismatch; I think your issue is a build plugin configuration collision.

The default build plugin configuration handling in Maven will automatically propagate all plugin configuration defined in a parent pom down to the child poms - which is usually exactly what you want.

But in your case, it's ruining your build. There is however, a simple way for you to declare what is essentially an exclusion -- it's just that you want to exclude build plugin config inheritance rather than build dependencies. You can turn off the customary plugin config propagation using the: <inherited> tag as shown here:

<build>
    <plugins>
        <plugin>
            <groupId>org.jacoco</groupId>
            <artifactId>jacoco-maven-plugin</artifactId>
            <version>0.8.5</version>
            <inherited>false</inherited>
            <!-- Additional build lifecycle goals,
                   plugin configuration entries, and
                      plugin execution definitions: ...
                                              -->
        </plugin>
     </plugins
 </build>
Britannic answered 21/5, 2022 at 12:57 Comment(3)
How do we add <exclusions> or <scope> with plugins as they seems to be only supported with dependencies ?Caddis
@AbhishekKumar - Added new content to my answer posting in response to the question in your comment and included details with respect to a proposed solution that should resolve the runtime java.lang.LinkageError failure(s).Britannic
Adding <inherited>false</inherited> didn't resolve the issue. I was looking at the [Jacoco documentation] (eclemma.org/jacoco/trunk/doc/…) looks like if we have jacoco-maven-plugin adding an agent directly through itCoverageAgent shouldn't be required at all.Caddis

© 2022 - 2024 — McMap. All rights reserved.