Jacoco - "Caused by: java.lang.ClassNotFoundException: org.jacoco.agent.rt.internal_6da5971.Offline"
Asked Answered
M

2

15

Trying to get coverage via jacoco using offline instrumentation (can't use on-the-fly instrumentation: due to powermock testcases) for a maven project.Added the jacocoagent.jar to classpath in surefire plugin as shown below. Renamed the "org.jacoco.agent-0.7.7.201606060606-runtime.jar" (from local maven repository) to "jacocoagent.jar" and kept that in the same folder where this pom.xml is residing.I'm hitting the below exception even after adding it to classpath.

snippet of pom.xml (surefire - plugin configuration)

       <plugin>
             <groupId>org.apache.maven.plugins</groupId>
             <artifactId>maven-surefire-plugin</artifactId>
             <configuration>
                     <forkmode>once</forkmode>
                    <additionalClasspathElements>
            <additionalClasspathElement>jacocoagent.jar</additionalClasspathElement>
                                        </additionalClasspathElements>
              </configuration>
     </plugin>

Exception seen on console:

#############
Number of foreign imports: 1
import: Entry[import  from realm ClassRealm[maven.api, parent: null]]

-----------------------------------------------------

        at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:166)
        ... 21 more
Caused by: java.lang.NoClassDefFoundError: org/jacoco/agent/rt/internal_6da5971/Offline
        at com.cisco.ise.ups.modelframework.hibernate.OracleNamingStrategy.$jacocoInit(OracleNamingStrategy.java)
        at com.cisco.ise.ups.modelframework.hibernate.OracleNamingStrategy.<clinit>(OracleNamingStrategy.java)
        at sun.misc.Unsafe.ensureClassInitialized(Native Method)
        at sun.reflect.UnsafeFieldAccessorFactory.newFieldAccessor(UnsafeFieldAccessorFactory.java:43)
        at sun.reflect.ReflectionFactory.newFieldAccessor(ReflectionFactory.java:142)
        at java.lang.reflect.Field.acquireFieldAccessor(Field.java:1082)
        at java.lang.reflect.Field.getFieldAccessor(Field.java:1063)
        at java.lang.reflect.Field.get(Field.java:387)
        at com.cisco.ise.ups.build.WorkflowRunnerMojo.namingStrategyInstance(WorkflowRunnerMojo.java:335)
        at com.cisco.ise.ups.build.WorkflowRunnerMojo.setupWorkflowEnvironment(WorkflowRunnerMojo.java:514)
        at com.cisco.ise.ups.build.WorkflowRunnerMojo.execute(WorkflowRunnerMojo.java:816)
        at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:134)
        ... 21 more
Caused by: java.lang.ClassNotFoundException: org.jacoco.agent.rt.internal_6da5971.Offline
        at org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy.loadClass(SelfFirstStrategy.java:50)
        at org.codehaus.plexus.classworlds.realm.ClassRealm.unsynchronizedLoadClass(ClassRealm.java:271)
        at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass(ClassRealm.java:247)
        at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass(ClassRealm.java:239)
        ... 33 more
[ERROR]
###############

Steps followed:

  1. "mvn compile" .
  2. "mvn org.jacoco:jacoco-maven-plugin:instrument"
  3. "mvn test" - Exception raised at this step.

Please let me know of how to get rid of this exception ? Was that the right place to add classpath?? (in surefire plugin) OR should it be specified some where??

Thank you.

Mainstay answered 16/10, 2016 at 6:18 Comment(5)
I'd bet that, if it is necessary to add libraries for testing, they should be specified in the <dependencies> section of the pom, with scope=test.Sugared
@LittleSanti: Tweaked pom.xml as per suggestion. Still issue (exception) persist. Added these lines under <dependencies> tab. <dependency> <groupId>org.jacoco</groupId> <artifactId>org.jacoco.agent</artifactId> <scope>test</scope> <classifier>runtime</classifier> <version>0.7.7.201606060606</version> </dependency>. Already jacocoagent.jar was downloaded and present on disk. It is just need to make this available on classpath so that instrumented classes can initiate it (eclemma.org/jacoco/trunk/doc/offline.html). Not sure, what still is missing !!!Mainstay
I see. Well... The other solution I think of is to set that dependency within the plugin's dependencies, because the plugins' classloader might be different from the tested code's classloader.Sugared
@LittleSanti: In the above snippet of code , it was already mentioned in <additionalClasspathElements> . right ? Can you tell me how to add classpath in maven pom.xml? basically, in working case., command look like this:(O/P of "ps aux | grep java") jre/bin/java -javaagent:/root/.m2/repository/org/jacoco/org.jacoco.agent/0.7.7.201606060606/org.jacoco.agent-0.7.7.201606060606-runtime.jar=destfile=target/jacoco.exec -jar target/surefire/surefirebooter5305632.jarMainstay
The only ways I know to add jars to a classpath in a pom.xml are the two mentioned before: The dependencies node and the plugins/pugin/dependencies node.Sugared
E
21

The classpath stuff on the surefire plugin is not necessary. You need to add a dependency to each module that has tests, like this:

<dependency>
    <groupId>org.jacoco</groupId>
    <artifactId>org.jacoco.agent</artifactId>
    <classifier>runtime</classifier>
    <scope>test</scope>
    <version>${your.jacoco.version}</version>
</dependency>

Make sure you don't miss the "classifier" part, or it won't work.

Full example from PowerMock project

Elutriate answered 11/8, 2017 at 23:8 Comment(0)
C
3

dr. macphail's trance article on getting Sonar + JaCoCo + PowerMock did the job for me:

  <!-- Provide information for coverage per test -->
  <profile>
     <id>coverage-per-test</id>
     <build>
        <plugins>
           <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-surefire-plugin</artifactId>
              <version>2.20</version>
              <configuration>
                 <argLine>${argLine} -Xverify:none</argLine>
                 <properties>
                    <property>
                       <name>listener</name>
                       <value>org.sonar.java.jacoco.JUnitListener</value>
                    </property>
                 </properties>
              </configuration>
           </plugin>
        </plugins>
     </build>

     <dependencies>
        <dependency>
           <groupId>org.sonarsource.java</groupId>
           <artifactId>sonar-jacoco-listeners</artifactId>
           <version>4.9.0.9858</version>
           <scope>test</scope>
        </dependency>
     </dependencies>
  </profile>

As mentioned in the comments section of the blog post :

In case your default argLine is not “simple” you might need to use the following snippet:

{argLine} -XX:-UseSplitVerifier

Otherwise you might run into ClassNotFoundException – e.g. java.lang.ClassNotFoundException: org.jacoco.agent.rt.RT

Clave answered 17/5, 2017 at 14:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.