Gradle 1.7: findbugsTest hangs forever

I am attempting to add Gradle’s FindBugs plugin to my multi-project build. Here is an excerpt of my root build.gradle:

...
    apply plugin: 'findbugs'
    ...
    ...
    findbugs {
        toolVersion = '2.0.1'
        effort = 'min'
        excludeFilter = rootProject.file('config/findbugs/exclude-filter.xml')
        reportLevel = 'high'
    }
    ...
    ...

Executing ./gradlew findbugsMain works fine. Executing ./gradlew findbugsIntegTest works fine. Executing ./gradlew findbugsTest hangs forever.

Running it with the –debug flag shows that the worker thread is actually getting an OutOfMemoryError.

15:45:06.100 [DEBUG] [system.out] 15:45:06.100 [DEBUG] [org.gradle.process.internal.child.ActionExecutionWorker] Starting Gradle Worker 2.
15:45:06.101 [DEBUG] [system.out] 15:45:06.101 [DEBUG] [org.gradle.api.plugins.quality.internal.findbugs.FindBugsWorkerServer] Executing FindBugs worker.
Scanning archives (139 / 449)out] 15:45:09.596 [QUIET] [system.out]
Scanning archives (207 / 449)
Scanning archives (275 / 449)
Scanning archives (412 / 449)
Scanning archives (449 / 449)
2 analysis passes to perform.out] 15:45:09.765 [QUIET] [system.out]
Pass 1: Analyzing classes (38 / 925) - 04% completeET] [system.out]
                                                                                                                                      iPass 1: Analyzing classes (78 / 925) - 08% complete
                                                                                                                                                      5Pass 1: Analyzing classes (117 / 925) - 12% complete
                                                                                                                                                      Pass 1: Analyzing classes (155 / 925) - 16% complete
                                                                                                                                                     cPass 1: Analyzing classes (233 / 925) - 25% complete
                                                                                                                                                     9Pass 1: Analyzing classes (271 / 925) - 29% complete
                                                                                                                                                     iPass 1: Analyzing classes (310 / 925) - 33% complete
                                                                                                                                                     lPass 1: Analyzing classes (348 / 925) - 37% complete
                                                                                                                                                     9Pass 1: Analyzing classes (387 / 925) - 41% complete
                                                                                                                                                     aPass 1: Analyzing classes (426 / 925) - 46% complete
                                                                                                                                                     cPass 1: Analyzing classes (464 / 925) - 50% complete
                                                                                                                                                      Pass 1: Analyzing classes (503 / 925) - 54% complete
                                                                                                                                                     :Pass 1: Analyzing classes (542 / 925) - 58% complete
                                                                                                                                                     5Pass 1: Analyzing classes (580 / 925) - 62% complete
                                                                                                                                                     sPass 1: Analyzing classes (619 / 925) - 66% complete
                                                                                                                                                     sPass 1: Analyzing classes (658 / 925) - 71% complete
                                                                                                                                                     )Pass 1: Analyzing classes (696 / 925) - 75% complete
                                                                                                                                                      Pass 1: Analyzing classes (774 / 925) - 83% complete
                                                                                                                                                      Pass 1: Analyzing classes (812 / 925) - 87% complete
                                                                                                                                                     zPass 1: Analyzing classes (851 / 925) - 92% complete
                                                                                                                                                     pPass 1: Analyzing classes (889 / 925) - 96% complete
                                                                                                                                                     9Pass 1: Analyzing classes (925 / 925) - 100% complete
15:45:57.846 [DEBUG] [system.err] 15:45:57.846 [ERROR] [system.err] The following classes needed for analysis were missing:
15:45:57.847 [DEBUG] [system.err] 15:45:57.846 [ERROR] [system.err]
 javax.annotation.Nonnull
15:45:57.847 [DEBUG] [system.err] 15:45:57.846 [ERROR] [system.err] Out of memory
15:45:57.847 [DEBUG] [system.err] 15:45:57.846 [ERROR] [system.err] Total memory: 129M
15:45:57.847 [DEBUG] [system.err] 15:45:57.847 [ERROR] [system.err]
free memory: 0M
...
...
...
15:45:58.487 [DEBUG] [system.out] 15:45:58.486 [DEBUG] [org.gradle.process.internal.child.ActionExecutionWorker] Stopping client connection.
15:45:58.488 [DEBUG] [system.err] 15:45:58.488 [ERROR] [system.err] java.lang.OutOfMemoryError: Java heap space
15:45:58.489 [DEBUG] [system.err] 15:45:58.489 [ERROR] [system.err]
at java.util.ArrayList.<init>(ArrayList.java:112)
15:45:58.489 [DEBUG] [system.err] 15:45:58.489 [ERROR] [system.err]
at edu.umd.cs.findbugs.ba.Frame.<init>(Frame.java:113)
15:45:58.489 [DEBUG] [system.err] 15:45:58.489 [ERROR] [system.err]
at edu.umd.cs.findbugs.ba.vna.ValueNumberFrame.<init>(ValueNumberFrame.java:62)
15:45:58.490 [DEBUG] [system.err] 15:45:58.489 [ERROR] [system.err]
at edu.umd.cs.findbugs.ba.vna.ValueNumberAnalysis.createFact(ValueNumberAnalysis.java:159)
15:45:58.490 [DEBUG] [system.err] 15:45:58.489 [ERROR] [system.err]
at edu.umd.cs.findbugs.ba.vna.ValueNumberAnalysis.createFact(ValueNumberAnalysis.java:55)
15:45:58.491 [DEBUG] [system.err] 15:45:58.490 [ERROR] [system.err]
at edu.umd.cs.findbugs.ba.BasicAbstractDataflowAnalysis.lookupOrCreateFact(BasicAbstractDataflowAnalysis.java:175)
15:45:58.491 [DEBUG] [system.err] 15:45:58.490 [ERROR] [system.err]
at edu.umd.cs.findbugs.ba.BasicAbstractDataflowAnalysis.getResultFact(BasicAbstractDataflowAnalysis.java:72)
15:45:58.491 [DEBUG] [system.err] 15:45:58.490 [ERROR] [system.err]
at edu.umd.cs.findbugs.ba.Dataflow.<init>(Dataflow.java:88)
15:45:58.492 [DEBUG] [system.err] 15:45:58.490 [ERROR] [system.err]
at edu.umd.cs.findbugs.ba.AbstractDataflow.<init>(AbstractDataflow.java:44)
15:45:58.492 [DEBUG] [system.err] 15:45:58.491 [ERROR] [system.err]
at edu.umd.cs.findbugs.ba.vna.ValueNumberDataflow.<init>(ValueNumberDataflow.java:36)
15:45:58.492 [DEBUG] [system.err] 15:45:58.491 [ERROR] [system.err]
at edu.umd.cs.findbugs.classfile.engine.bcel.ValueNumberDataflowFactory.analyze(ValueNumberDataflowFactory.java:74)
15:45:58.493 [DEBUG] [system.err] 15:45:58.491 [ERROR] [system.err]
at edu.umd.cs.findbugs.classfile.engine.bcel.ValueNumberDataflowFactory.analyze(ValueNumberDataflowFactory.java:46)
15:45:58.493 [DEBUG] [system.err] 15:45:58.492 [ERROR] [system.err]
at edu.umd.cs.findbugs.classfile.impl.AnalysisCache.analyzeMethod(AnalysisCache.java:387)
15:45:58.493 [DEBUG] [system.err] 15:45:58.492 [ERROR] [system.err]
at edu.umd.cs.findbugs.classfile.impl.AnalysisCache.getMethodAnalysis(AnalysisCache.java:340)
15:45:58.493 [DEBUG] [system.err] 15:45:58.493 [ERROR] [system.err]
at edu.umd.cs.findbugs.ba.ClassContext.getMethodAnalysis(ClassContext.java:1005)
15:45:58.494 [DEBUG] [system.err] 15:45:58.493 [ERROR] [system.err]
at edu.umd.cs.findbugs.ba.ClassContext.getValueNumberDataflow(ClassContext.java:334)
15:45:58.494 [DEBUG] [system.err] 15:45:58.493 [ERROR] [system.err]
at edu.umd.cs.findbugs.detect.FindNullDeref.findPreviouslyDeadBlocks(FindNullDeref.java:287)
15:45:58.494 [DEBUG] [system.err] 15:45:58.494 [ERROR] [system.err]
at edu.umd.cs.findbugs.detect.FindNullDeref.analyzeMethod(FindNullDeref.java:257)
15:45:58.495 [DEBUG] [system.err] 15:45:58.494 [ERROR] [system.err]
at edu.umd.cs.findbugs.detect.FindNullDeref.visitClassContext(FindNullDeref.java:205)
15:45:58.495 [DEBUG] [system.err] 15:45:58.494 [ERROR] [system.err]
at edu.umd.cs.findbugs.DetectorToDetector2Adapter.visitClass(DetectorToDetector2Adapter.java:74)
15:45:58.495 [DEBUG] [system.err] 15:45:58.495 [ERROR] [system.err]
at edu.umd.cs.findbugs.FindBugs2.analyzeApplication(FindBugs2.java:1193)
15:45:58.496 [DEBUG] [system.err] 15:45:58.495 [ERROR] [system.err]
at edu.umd.cs.findbugs.FindBugs2.execute(FindBugs2.java:279)
15:45:58.496 [DEBUG] [system.err] 15:45:58.495 [ERROR] [system.err]
at org.gradle.api.plugins.quality.internal.findbugs.FindBugsExecuter.runFindbugs(FindBugsExecuter.java:44)
15:45:58.496 [DEBUG] [system.err] 15:45:58.496 [ERROR] [system.err]
at org.gradle.api.plugins.quality.internal.findbugs.FindBugsWorkerServer.execute(FindBugsWorkerServer.java:44)
15:45:58.497 [DEBUG] [system.err] 15:45:58.496 [ERROR] [system.err]
at org.gradle.api.plugins.quality.internal.findbugs.FindBugsWorkerServer.execute(FindBugsWorkerServer.java:35)
15:45:58.497 [DEBUG] [system.err] 15:45:58.497 [ERROR] [system.err]
at org.gradle.api.plugins.quality.internal.findbugs.FindBugsWorkerServer.execute(FindBugsWorkerServer.java:26)
15:45:58.497 [DEBUG] [system.err] 15:45:58.497 [ERROR] [system.err]
at org.gradle.process.internal.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:78)
15:45:58.498 [DEBUG] [system.err] 15:45:58.497 [ERROR] [system.err]
at org.gradle.process.internal.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:35)
15:45:58.498 [DEBUG] [system.err] 15:45:58.497 [ERROR] [system.err]
at org.gradle.process.internal.child.ImplementationClassLoaderWorker.execute(ImplementationClassLoaderWorker.java:81)
15:45:58.498 [DEBUG] [system.err] 15:45:58.498 [ERROR] [system.err]
at org.gradle.process.internal.child.ImplementationClassLoaderWorker.execute(ImplementationClassLoaderWorker.java:37)
15:45:58.499 [DEBUG] [system.err] 15:45:58.498 [ERROR] [system.err]
at org.gradle.process.internal.child.IsolatedApplicationClassLoaderWorker.call(IsolatedApplicationClassLoaderWorker.java:48)
15:45:58.499 [DEBUG] [system.err] 15:45:58.498 [ERROR] [system.err]
at org.gradle.process.internal.child.IsolatedApplicationClassLoaderWorker.call(IsolatedApplicationClassLoaderWorker.java:30)
15:45:58.821 [DEBUG] [org.gradle.process.internal.DefaultExecHandle] Changing state to: FAILED
15:45:58.822 [INFO] [org.gradle.process.internal.DefaultExecHandle] Process 'Gradle Worker 2' finished with exit value 1 (state: FAILED)
> Building > :dm-base:findbugsTest

So, I went looking for a way to increase the heap size. I stumbled upon a maxHeapSize property; however, it doesn’t seem to take affect. When I added this:

...
    findbugs {
        ...
        maxHeapSize = '512m'
        ...
    }
    ...

I still see this in the –debug output:

15:45:57.847 [DEBUG] [system.err] 15:45:57.846 [ERROR] [system.err] Out of memory
15:45:57.847 [DEBUG] [system.err] 15:45:57.846 [ERROR] [system.err] Total memory: 129M
15:45:57.847 [DEBUG] [system.err] 15:45:57.847 [ERROR] [system.err]
free memory: 0M

Interestingly, I can get findbugsTest to work fine in the sub-projects that do not contain any Spock specs; it’s only the ones that contains Spock specs that hang. Not sure what that means, if anything. Further, findbugsIntegTest works in all sub-projects…even ones with Spock specs.

OK, after some more Googling, I’ve come up with this:

tasks.withType(FindBugs) {
        maxHeapSize = '384m'
    }

The key is that it has to be be set on a task. Maybe I’m not reading the documentation correctly, but I’m not sure how/where that is called out.

However, the more I thought about it, running FindBugs against Groovy/Spock code didn’t seem to make sense. I did some more Googling and came across a few articles that seemed to be in agreement – though it’ll work, there will be lots of undesirable noise. So, I decided I needed to exclude the Groovy/Spock test code; yet more Googling turned up an old question from this forum that yields a solution:

tasks.withType(FindBugs) {
        def ft = classes
        ft.exclude '**/*Spec*'
        classes = files(ft)
    }

However, I’m wondering if this is the best solution. I wonder why this doesn’t work:

tasks.withType(FindBugs) {
        classes.exclude '**/*Spec*'
    }

???