JUnit test fails with NoClassDefFoundError only when maxParallelForks > 1

Hi–

If I run my unit tests with maxParallelForks=1, all is fine, but with maxParallelForks=3, they fail with a initializationError/NoClassDefFoundError exception – the classes in question are some within my project and I see evidence of them existing. That seems strange to me since uh, I would have expected it to be pretty consistent in that regard and to add to the weirdness, my coworkers or other machines do not have this issue. Do you have any ideas of what might be going wonky or how to diagnose this? This is with Gradle 1.2. Thanks for any assistance!

=== java.lang.NoClassDefFoundError: [a-super-class-of-our-unit-test]

at java.lang.Class.forName0(Native Method)

at java.lang.Class.forName(Class.java:247)

at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:51)

at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:42)

at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:75)

at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:49)

at sun.reflect.GeneratedMethodAccessor10.invoke(Unknown Source)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

at java.lang.reflect.Method.invoke(Method.java:597)

at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)

at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)

at org.gradle.messaging.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)

at org.gradle.messaging.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)

at $Proxy2.processTestClass(Unknown Source)

at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:103)

at sun.reflect.GeneratedMethodAccessor9.invoke(Unknown Source)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

at java.lang.reflect.Method.invoke(Method.java:597)

at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)

at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)

at org.gradle.messaging.remote.internal.TypeCastDispatch.dispatch(TypeCastDispatch.java:30)

at org.gradle.messaging.remote.internal.WorkerProtocol.handleIncoming(WorkerProtocol.java:53)

at org.gradle.messaging.remote.internal.WorkerProtocol.handleIncoming(WorkerProtocol.java:31)

at org.gradle.messaging.remote.internal.ProtocolStack$ProtocolStage.handleIncoming(ProtocolStack.java:167)

at org.gradle.messaging.remote.internal.ProtocolStack$BottomStage.handleIncoming(ProtocolStack.java:277)

at org.gradle.messaging.remote.internal.ProtocolStack$BottomConnection$1.run(ProtocolStack.java:299)

at org.gradle.messaging.remote.internal.ProtocolStack$ExecuteRunnable.dispatch(ProtocolStack.java:120)

at org.gradle.messaging.remote.internal.ProtocolStack$ExecuteRunnable.dispatch(ProtocolStack.java:116)

at org.gradle.messaging.dispatch.AsyncDispatch.dispatchMessages(AsyncDispatch.java:132)

at org.gradle.messaging.dispatch.AsyncDispatch.access$000(AsyncDispatch.java:33)

at org.gradle.messaging.dispatch.AsyncDispatch$1.run(AsyncDispatch.java:72)

at org.gradle.internal.concurrent.DefaultExecutorFactory$StoppableExecutorImpl$1.run(DefaultExecutorFactory.java:66)

at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)

at java.lang.Thread.run(Thread.java:662) ===

eyt*

Please use HTML ‘code’ tags for all code snippets and stack traces.

Does this error occur consistently? What is the InitializationError about? Are you running multiple builds in parallel, or doing anything else that could corrupt the build/ directory? Can you double-check if the class file of the superclass exists in build/classes/test when the error occurs (assuming it’s from the same project)? Are you on a different OS than your coworkers? Does the info or debug log show anything suspicious, in particular “close” to the error?

Hi Peter–

Yes, this error occurs consistently and always the same number and locations and I am on the same Linux distribution, version, JDK, etc. as my coworkers – my Laptop has the same environment as my desktop and does not have this issue, albeit its slow…

The exception pasted in the above is the initializationError message. Yes, the class is in the build/classes/test/ – after doing more tests, I see that this error does not occur if there are 2 or 4 maxParallelForks; it only happens on 3.

Still parsing through and comparing the logs, but I see:

Running test: test initializationError(com.mycompany.tests.MyUnitTest)

which would seem to imply that the error is detected before hand. I’m not sure how gradle handles test detection verses execution, so that could be something interesting or not.

I’ll update if I notice anything else interesting in the log… Thanks for any insight.

eyt*

What happens is that the test class cannot be loaded, because its superclass isn’t found. I can’t say why; first time I hear about this problem.

I haven’t seen that error, either. All forked test worker processes have the same classpath, only the set of test classes to execute is different.

Is there anything peculiar about this super class? We use this pattern in our code base, too. Typically the super class is declared as abstract.

Can you also submit the output of gradle -v?

Would it be possible if you created a minimal project that reproduces the issue?