How can you ensure the -javaagent JVM arg implicitly added by jacoco comes BEFORE all other -javaagent JVM arguments on the command line?

We are using spring + aspectj and require the following JVM args to be present for our tests:

 -javaagent:/path-to/aspectjweaver-1.9.2.jar -javaagent:/path-to/spring-instrument-5.1.5.RELEASE.jar 

Our tests run fine, but when we try to use jacoco, we get warnings like this during jacocoTestReport for some classes:

05:49:27  > Task :core-service:jacocoTestReport
05:49:27  [ant:jacocoReport] Classes in bundle 'core-service' do no match with execution data. For report generation the same class files must be used as at runtime.
05:49:27  [ant:jacocoReport] Execution data for class com/acme/FooService does not match.
05:49:27  [ant:jacocoReport] Execution data for class com/acme/BarService does not match.

After researching this, it seems like the jacoco recommendation is to make sure that the -javaagent argument for the jacoco agent is the FIRST javaagent on the command line.

See this answer, key excerpt:

"If you use another Java agent make sure the JaCoCo agent is specified at FIRST in the command line. This way the JaCoCo agent should see the original class files."

NOTE: the jacoco task will implicitly add its own -javaagent JVM arg, but it always ends up later on the command line in my case.

This is also complicted somewhat by the fact that the jacoco -javaagent argument is not static (it has a myriad of options concatenated after the jar reference, that are a function of the specific use case).

Here is an example java invocation for our tests, as generated by gradle (abbreviated & reformatted for readability):

/usr/lib/jvm/adoptopenjdk-11-hotspot-amd64/bin/java \
   -Dorg.gradle.native=false \
   -javaagent:/path/to/spring-instrument-5.1.5.RELEASE.jar \
   -javaagent:/path/to/aspectjweaver-1.9.2.jar \
   -javaagent:build/tmp/expandedArchives/org.jacoco.agent-0.8.5.jar_6a2df60c47de373ea127d14406367999/jacocoagent.jar=destfile=build/jacoco/test.exec,append=true,excludes=**/xyz/**:**/com/someother/**:**/*.zip,inclnolocationclasses=false,dumponexit=true,output=file,jmx=false \
   @/tmp/gradle-worker-classpath12976595675824598txt \
   -Xmx512m \
   -Dfile.encoding=UTF-8 -Duser.country=US -Duser.language=en -Duser.variant -ea \
    worker.org.gradle.process.internal.worker.GradleWorkerMain

We are inserting our other JVM -javaagent arguments like this:

test {
   jacoco {
      enabled = true
   }

   // NOTE: have also tried moving this to other points in the lifecycle (still always end up before jacoco's)
   doFirst {
      configurations.javaAgent.files.each {
         jvmArgs "-javaagent:${it}"
      }
   }
}

Tool versions:

  • Java 11
  • Gradle 6.7.1
0

There are 0 best solutions below