Jacoco+gradle taskdef A class needed by class org.jacoco.ant.InstrumentTask canno t be found

I’m trying to get jacoco+gradle work together. But I got a strange exception.

What I did:

1.Downloaded gradle 2.2.1 and configured env variables, etc.

2.Downloaded jacoco 0.7.1 from http://www.eclemma.org/jacoco/

3.added:

apply plugin: ‘jacoco’

and

buildTypes {

debug {

testCoverageEnabled true … in the build.gradle

4.ran gradle build

5.I got an error saying the jacoco agent jar cannot be found, etc. Error message showed it tried to search files under C:\Program Files (x86)\Android\android-sdk\extras\android\m2repository… etc.

6.I manually put the jacoco jar files in the place where the error message mentioned and the error message disappeared.

7.Then I ran gradle build again. I got the following new error when running the built-in instrumentDebug task:

Caused by: : taskdef A class needed by class org.jacoco.ant.InstrumentTask cannot be found: org/jacoco/core/runtime/IExecutionDataAccessorGenerator using the classloader AntClassLoader[C:\Program Files (x86)\Android\android-sdk\extras\android\m2repository\org\jacoco\org.jacoco.ant\0.7.1.201405082137\org.jacoco.ant-0.7.1.201405082137.jar]

at org.apache.tools.ant.taskdefs.Definer.addDefinition(Definer.java:612)

at org.apache.tools.ant.taskdefs.Definer.execute(Definer.java:237)

at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:292)

at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)

at org.gradle.api.internal.project.ant.BasicAntBuilder.nodeCompleted(BasicAntBuilder.java:77)

at org.gradle.api.internal.project.ant.BasicAntBuilder.doInvokeMethod(BasicAntBuilder.java:92)

at com.android.build.gradle.internal.coverage.JacocoInstrumentTask.instrument(JacocoInstrumentask.groovy:51)

at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:63)

at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.doExecute(AnnotationProcessingTaskFactory.java:218)

at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:211)

Caused by: java.lang.ClassNotFoundException:

at org.jacoco.core.runtime.IExecutionDataAccessorGenerator

at org.apache.tools.ant.AntClassLoader.findClassInComponents(AntClassLoader.java:1366)

at org.apache.tools.ant.AntClassLoader.findClass(AntClassLoader.java:1315)

at org.apache.tools.ant.AntClassLoader.loadClass(AntClassLoader.java:1068)…

When I used process monitor (My dev machine is Win 7), I saw there was no access to org.jacoco.core-0.7.1.201405082137.jar,which the org.jacoco.ant.InstrumentTask class resides in. So I think the gradle did not pass the file path to org.apache.tools.ant.AntClassLoader correctly.

I have tried below ways but none of them worked:

Add all jacoco jar files to CLASSPATH environment variable. Add the jacoco jar files to ant libs, gradle libs,gradle libs/plugins, folder. Look at source code of gradle 2.2.1. Clueless at this moment…

Does anyone know how to resolve this problem?

Thanks in advance!

I do not have access to a PC now, so I cannot test this, but you should not need to download jacoco. Not that it should have the effect you see, though.

Hi Stig Kleppe-Jørgensen,

Thanks for your reply. If I don’t download jacoco jars, I was stopped at #5. The error message shows that gradle tries to find jacoco jars from C:\Program Files (x86)\Android\android-sdk\extras\android\m2repository…

Am I missing something?

The first error message I got was as below. After I manually put jar files under the folder the error disappeared. But then I encountered the problem mentioned in my original post:

FAILURE: Build failed with an exception.

  • What went wrong: Could not resolve all dependencies for configuration ‘:AndroidJD-Phone:androidJa cocoAgent’. > Could not find org.jacoco:org.jacoco.agent:0.7.1.201405082137.

Searched in the following locations:

file:/C:/Program Files (x86)/Android/android-sdk/extras/android/m2reposito ry/org/jacoco/org.jacoco.agent/0.7.1.201405082137/org.jacoco.agent-0.7.1.2014050 82137.pom

file:/C:/Program Files (x86)/Android/android-sdk/extras/android/m2reposito ry/org/jacoco/org.jacoco.agent/0.7.1.201405082137/org.jacoco.agent-0.7.1.2014050 82137.jar

file:/C:/Program Files (x86)/Android/android-sdk/extras/google/m2repositor y/org/jacoco/org.jacoco.agent/0.7.1.201405082137/org.jacoco.agent-0.7.1.20140508 2137.pom

file:/C:/Program Files (x86)/Android/android-sdk/extras/google/m2repositor y/org/jacoco/org.jacoco.agent/0.7.1.201405082137/org.jacoco.agent-0.7.1.20140508 2137.jar

Required by:

4:AndroidJD-Phone:unspecified

Update: I just found when executing InstrumentDebug task, the gradle start a new process with below command:

“C:\Program Files\Java\jdk1.8.0_25\bin\java.exe” -XX:MaxPermSize=512m -Xmx2048m -Dfile.encoding=UTF-8 -Duser.country=CN -Duser.language=zh -Duser.variant -cp D:\gradle-2.2.1\gradle-2.2.1\lib\gradle-launcher-2.2.1.jar org.gradle.launcher.daemon.bootstrap.GradleDaemon 2.2.1 D:\gradle-2.2.1\gradle-2.2.1\daemon 120000 744501ac-32c1-4930-82bd-59e0a9e2b92d -XX:MaxPermSize=512m -Xmx2048m -Dfile.encoding=UTF-8 -Duser.country=CN -Duser.language=zh -Duser.variant

As you can see the class path is hard coded, which overwrites what defined in environment variable. So the required core lib of jacoco could not be found and thus caused this problem. I’m now trying to see where this process is started and whether there is a way to change the -cp option.

I finally found this process is started by gradle-launcher-2.2.1.jar. See below code. I’m now trying to see whether it’s possible to change DefaultModuleRegistry and make registry.getGradleHome() == null. In the meantime could anyone who has successfully used jacoco+gradle tell me which version of gradle are you using?

public DaemonStartupInfo startDaemon() { DefaultModuleRegistry registry = new DefaultModuleRegistry(); Set bootstrapClasspath = new LinkedHashSet(); bootstrapClasspath.addAll(registry.getModule(“gradle-launcher”).getImplementationClasspath().getAsFiles()); if (registry.getGradleHome() == null)

{

bootstrapClasspath.addAll(registry.getFullClasspath()); } if (bootstrapClasspath.isEmpty()) {

throw new IllegalStateException(“Unable to construct a bootstrap classpath when starting the daemon”); }

new JvmVersionValidator().validate(this.daemonParameters); List daemonArgs = new ArrayList(); daemonArgs.add(this.daemonParameters.getEffectiveJavaExecutable()); List daemonOpts = this.daemonParameters.getEffectiveJvmArgs(); LOGGER.debug(“Using daemon opts: {}”, daemonOpts); daemonArgs.addAll(daemonOpts); daemonArgs.add("-cp"); daemonArgs.add(CollectionUtils.join(File.pathSeparator, bootstrapClasspath)); daemonArgs.add(GradleDaemon.class.getName()); daemonArgs.add(GradleVersion.current().getVersion()); daemonArgs.add(this.daemonDir.getBaseDir().getAbsolutePath()); daemonArgs.add(String.valueOf(this.daemonParameters.getIdleTimeout())); daemonArgs.add(this.daemonParameters.getUid());

… }