Errors when running Jacoco plugin using Java 8 on multi project build

I’m having problems getting the Jacoco plugin to work with our existing Java 8 multi-project build (Gradle 1.10).

This is our setup: - Java 8 - Multiple projects (some nested a couple of levels deep) - Gradle 1.10 via the wrapper - A combination of JUnit unit tests and (JUnit) integration tests (using an integrationTest configuration, tests stored in src/main/integrationTest) - Jacoco (using toolVersion = “0.7.0.201403182114” so that it works for Java 8)

If I remove the Jacoco plugin, everything builds fine, and all the tests execute and pass, with the unit tests and integration tests writing their results to different locations. This part is all fine. But once I add Jacoco, the tests all start failing, and the errors all look similar to this (I’ve replaced all references to our own private class names with dummy values - apologies if that makes anything confusing):

08:54:40.088 [DEBUG] [TestEventLogger] Gradle Worker 3 STARTED 08:54:40.092 [QUIET] [system.out] 08:54:40.092 [DEBUG] [org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor] Executing test class my.TestClass 08:54:40.096 [DEBUG] [TestEventLogger]

08:54:40.096 [DEBUG] [TestEventLogger] my.TestClass STARTED 08:54:40.210 [DEBUG] [TestEventLogger]

08:54:40.210 [DEBUG] [TestEventLogger] my.TestClass > testXyz STARTED 08:54:40.282 [DEBUG] [TestEventLogger]

08:54:40.283 [DEBUG] [TestEventLogger] my.TestClass > testXyz FAILED 08:54:40.283 [DEBUG] [TestEventLogger]

java.lang.ExceptionInInitializerError 08:54:40.283 [DEBUG] [TestEventLogger]

at my.DomainClass.(DomainClass.java:51) 08:54:40.283 [DEBUG] [TestEventLogger]

at my.TestClass.setup(TestClass.java:34) 08:54:40.283 [DEBUG] [TestEventLogger]

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 08:54:40.283 [DEBUG] [TestEventLogger]

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 08:54:40.283 [DEBUG] [TestEventLogger]

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 08:54:40.283 [DEBUG] [TestEventLogger]

at java.lang.reflect.Method.invoke(Method.java:483) 08:54:40.283 [DEBUG] [TestEventLogger]

at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47) 08:54:40.283 [DEBUG] [TestEventLogger]

at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 08:54:40.284 [DEBUG] [TestEventLogger]

at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44) 08:54:40.284 [DEBUG] [TestEventLogger]

at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24) 08:54:40.284 [DEBUG] [TestEventLogger]

at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271) 08:54:40.284 [DEBUG] [TestEventLogger]

at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70) 08:54:40.284 [DEBUG] [TestEventLogger]

at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) 08:54:40.284 [DEBUG] [TestEventLogger]

at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) 08:54:40.284 [DEBUG] [TestEventLogger]

at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) 08:54:40.284 [DEBUG] [TestEventLogger]

at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) 08:54:40.284 [DEBUG] [TestEventLogger]

at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) 08:54:40.284 [DEBUG] [TestEventLogger]

at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) 08:54:40.284 [DEBUG] [TestEventLogger]

at org.junit.runners.ParentRunner.run(ParentRunner.java:309) 08:54:40.284 [DEBUG] [TestEventLogger]

at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:86) 08:54:40.284 [DEBUG] [TestEventLogger]

at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:49) 08:54:40.284 [DEBUG] [TestEventLogger]

at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:69) 08:54:40.284 [DEBUG] [TestEventLogger]

at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:50) 08:54:40.285 [DEBUG] [TestEventLogger]

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 08:54:40.285 [DEBUG] [TestEventLogger]

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 08:54:40.285 [DEBUG] [TestEventLogger]

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 08:54:40.285 [DEBUG] [TestEventLogger]

at java.lang.reflect.Method.invoke(Method.java:483) 08:54:40.285 [DEBUG] [TestEventLogger]

at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35) 08:54:40.285 [QUIET] [system.out] 08:54:40.284 [DEBUG 08:54:40.285 [DEBUG] [TestEventLogger]

at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) 08:54:40.285 [DEBUG] [TestEventLogger]

at org.gradle.messaging.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32) 08:54:40.285 [DEBUG] [TestEventLogger]

at org.gradle.messaging.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93) 08:54:40.285 [DEBUG] [TestEventLogger]

at com.sun.proxy.$Proxy2.processTestClass(Unknown Source) 08:54:40.285 [DEBUG] [TestEventLogger]

at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:103) 08:54:40.285 [DEBUG] [TestEventLogger]

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 08:54:40.285 [DEBUG] [TestEventLogger]

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 08:54:40.285 [DEBUG] [TestEventLogger]

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 08:54:40.285 [DEBUG] [TestEventLogger]

at java.lang.reflect.Method.invoke(Method.java:483) 08:54:40.285 [DEBUG] [TestEventLogger]

at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35) 08:54:40.286 [DEBUG] [TestEventLogger]

at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) 08:54:40.286 [DEBUG] [TestEventLogger]

at org.gradle.messaging.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:355) 08:54:40.286 [DEBUG] [TestEventLogger]

at org.gradle.internal.concurrent.DefaultExecutorFactory$StoppableExecutorImpl$1.run(DefaultExecutorFactory.java:64) 08:54:40.286 [DEBUG] [TestEventLogger]

at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 08:54:40.286 [DEBUG] [TestEventLogger]

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 08:54:40.286 [DEBUG] [TestEventLogger]

at java.lang.Thread.run(Thread.java:744) 08:54:40.286 [DEBUG] [TestEventLogger]

08:54:40.286 [DEBUG] [TestEventLogger]

Caused by: 08:54:40.286 [DEBUG] [TestEventLogger]

java.lang.ArrayIndexOutOfBoundsException: 3 08:54:40.285 [QUIET] [system.out] ] [org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor]

08:54:40.286 [DEBUG] [TestEventLogger]

at <one of my classes - snipped>.(MyClass.java:23) 08:54:40.286 [DEBUG] [TestEventLogger]

… 44 more

08:54:40.290 [DEBUG] [TestEventLogger]

java.lang.NoClassDefFoundError: Could not initialize class

Initially I thought this may have been related to GRADLE-2860, but the workaround for that issue (setting the user.dir system property to the test working directory) does not make any difference for me.

Any help or pointers greatly appreciated - a day spent searching for solutions has so far got me nowhere. Our setup looks very similar to other setups that seem to work (e.g. http://jsebfranck.blogspot.fr/2014/01/tests-coverage-sonar-jacoco-gradle.html), which makes me wonder if it may be related to Java 8.

Can you try with Gradle 1.12-rc-1 (or rc-2 once it’s out)?

Just tried with RC2, but still no luck.

Some more information though - I noticed that one of the test classes passes (25/25 tests pass), but in all the other classes, every test fails. And these failing tests all seem to be failing around the same point - when trying to run the static initializer code (setting up constants) inside a @FunctionalInterface called Validator (one of our own classes).

Interestingly, the very first test seems to “see” the Validator, as it fails here:

Caused by: java.lang.ArrayIndexOutOfBoundsException: 3

at my.secret.package.Validator.(Validator.java:23)

(line 23 is the declaration + instantiation of a field in the Validator interface - an instance of Validator itself)

But then all subsequent tests fail with:

java.lang.NoClassDefFoundError: Could not initialize class my.secret.package.Validator

The Validator exists in a separate subproject, but as I said yesterday, all the tests pass if I remove the Jacoco plugin, so it isn’t a simple case of a missing dependency.

Looks very much like a JaCoCo related problem to me. Perhaps it still has some issues with Java 8. I don’t see any indication that this is a Gradle related problem.

According to the stack trace, the ‘ArrayIndexOutOfBoundsException’ happens in a static initializer. Since the class can’t be initialized, subsequent 'NoClassDefFoundError’s aren’t surprising.

For the benefit of anyone else who ends up banging their head on their desk for a day like I did because of this issue, the problem turned out to be this:

https://github.com/jacoco/jacoco/issues/201

In other words, Peter was correct (thanks for the hint) and JaCoCo does not have correct support for Java 8 (at least not in an official release).

We were able to resolve this by using the latest JaCoCo snapshot, where this issue has been fixed. It should be fixed properly in 0.7.1.