Sonar Scanner OOM

[Sonar Scanner OutOfMemoryError Resolved by Server-Side Memory Increase — Why?]

Versions

  • SonarQube Server: sonarqube-2025.3.0.108892 (Enterprise Edition)
  • Scanner: SonarScanner for Gradle 5.1.0.4882
  • Deployment: SonarQube deployed using zip on a Windows with 32 GB RAM

What I’m Trying to Achieve

I’m analyzing a very large monorepo (~100,00 Java classes, 3M lines) using the SonarScanner from Gradle. The goal is to run nightly full scans of the entire codebase and publish the results to SonarQube Server without memory issues or failures.


What Happened

After running for ~6 hours, the scanner crashes with the following error:

Picked up JAVA_TOOL_OPTIONS: -XX:+UseContainerSupport
Picked up JAVA_TOOL_OPTIONS: -XX:+UseContainerSupport
Picked up JAVA_TOOL_OPTIONS: -XX:+UseContainerSupport
isAlive was interrupted
java.lang.InterruptedException: null
        at java.base/java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:386)
        at java.base/java.util.concurrent.CompletableFuture.get(CompletableFuture.java:2073)
        at java.net.http/jdk.internal.net.http.HttpClientImpl.send(HttpClientImpl.java:553)
        at java.net.http/jdk.internal.net.http.HttpClientFacade.send(HttpClientFacade.java:123)
        at org.sonar.plugins.javascript.bridge.Http$JdkHttp.get(Http.java:71)
        at org.sonar.plugins.javascript.bridge.BridgeServerImpl.isAlive(BridgeServerImpl.java:462)
        at org.sonar.plugins.javascript.bridge.BridgeServerImpl.heartbeat(BridgeServerImpl.java:158)
        at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
        at java.base/java.util.concurrent.FutureTask.runAndReset(FutureTask.java:305)
        at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:305)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
        at java.base/java.lang.Thread.run(Thread.java:833)


FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':sonar'.
> Java heap space

* Try:
> Run with --debug option to get more log output.

* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':sonar'.
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.lambda$executeIfValid$1(ExecuteActionsTaskExecuter.java:142)
        at org.gradle.internal.Try$Failure.ifSuccessfulOrElse(Try.java:282)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeIfValid(ExecuteActionsTaskExecuter.java:140)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:128)
        at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:77)
        at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:46)
        at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:51)
        at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57)
        at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:57)
        at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:199)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
        at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)
        at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
        at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:73)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52)
        at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:69)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:322)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:309)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:302)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:288)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:462)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:379)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
        at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:49)
Caused by: java.lang.OutOfMemoryError: Java heap space
        at B.A.A.A.A.D$_D.<init>(na:1146)
        at B.A.A.A.A.D.iterator(na:1079)
        at com.sonarsource.A.B.H.F$_B.A(na:1541)
        at com.sonarsource.A.B.H.F.A(na:499)
        at com.sonarsource.A.B.H.F.B(na:424)
        at com.sonarsource.A.B.N.C(na:2937)
        at com.sonarsource.A.B.N.B(na:3361)
        at com.sonarsource.A.B.S.D(na:2246)
        at com.sonarsource.A.B.L.A(na:1012)
        at com.sonarsource.A.B.W.A(na:798)
        at com.sonarsource.A.B.W.A(na:2073)
        at com.sonarsource.A.B.W.A(na:1833)
        at com.sonarsource.A.B.W.C(na:373)
        at com.sonarsource.A.B.W.A(na:1173)
        at com.sonarsource.A.B.W.A(na:3509)
        at com.sonarsource.A.B.W.A(na:2966)
        at com.sonarsource.A.A.A.C.F.executeChecksOnFunction(na:163)
        at com.sonarsource.A.A.A.C.F.A(na:1030)
        at com.sonarsource.A.A.A.C.F.executeChecks(na:332)
        at com.sonarsource.A.A.A.C.F.executeSensor(na:2224)
        at com.sonarsource.A.A.A.C.F.execute(na:2887)
        at com.sonarsource.A.G.execute(na:362)
        at org.sonar.scanner.sensor.AbstractSensorWrapper.analyse(AbstractSensorWrapper.java:64)
        at org.sonar.scanner.sensor.ModuleSensorsExecutor.execute(ModuleSensorsExecutor.java:88)
        at org.sonar.scanner.sensor.ModuleSensorsExecutor.execute(ModuleSensorsExecutor.java:64)
        at org.sonar.scanner.scan.SpringModuleScanContainer.doAfterStart(SpringModuleScanContainer.java:82)
        at org.sonar.core.platform.SpringComponentContainer.startComponents(SpringComponentContainer.java:226)
        at org.sonar.core.platform.SpringComponentContainer.execute(SpringComponentContainer.java:205)
        at org.sonar.scanner.scan.SpringProjectScanContainer.scan(SpringProjectScanContainer.java:201)
        at org.sonar.scanner.scan.SpringProjectScanContainer.scanRecursively(SpringProjectScanContainer.java:197)
        at org.sonar.scanner.scan.SpringProjectScanContainer.doAfterStart(SpringProjectScanContainer.java:170)
        at org.sonar.core.platform.SpringComponentContainer.startComponents(SpringComponentContainer.java:226)

From the logs, it’s clear that the error occurs while the scanner is checking status with the server.


What I Tried

Initially, I focused on the scanner side:

  • Set SONAR_SCANNER_OPTS=-Xmx6g
  • Tuned Gradle memory (org.gradle.jvmargs=-Xmx6g -Xms2g)

Despite this, the error persisted.

Eventually, I increased memory on the SonarQube Server:

properties

# sonar.properties
sonar.search.javaOpts = -Xmx4g -Xms4g
sonar.web.javaOpts    = -Xmx24g -Xms16g
sonar.ce.javaOpts     = -Xmx16g -Xms16g

After this, the scanner no longer crashes, and analysis completes successfully.


Question

While the OOM error appears on the scanner side, increasing server memory resolved it. Can someone explain:

  • Why exactly does server-side memory affect scanner-side stability?
  • Is the scanner holding large data while waiting for a slow response from the server?
  • Are there any SonarQube best practices for analyzing extremely large Java projects to avoid this situation?

I’d really appreciate any clarification or official guidance. Thanks!

Hey @Jemin_Shah,

I really doubt there’s a true correlation here. I don’t want to question your findings, but it contradicts everything I know about how SonarQube works!

Could you try reverting the SonarQube Server memory changes and check if the scanner starts crashing again?

I would also want to know more about what the scanner is doing at this point. You should be able to get more output from the scanner ( gradle sonar --info or gradle sonar --debug)

Hi @Colin,

Let me share various log files.
I have amended properties listed below.

sonar.web.javaOpts=-Xmx16G -Xms8G -XX:+HeapDumpOnOutOfMemoryError
sonar.ce.javaOpts=-Xmx16G -Xms8G -XX:+HeapDumpOnOutOfMemoryError
sonar.search.javaOpts=-Xmx3G -Xms3G -XX:MaxDirectMemorySize=1G -XX:+HeapDumpOnOutOfMemoryError

sonar-OOM-CE_16GB-Web_16GB-Search-3GB.log (12.8 MB)
sonar-OOM-CE_8GB-Web_8GB-Search-3GB.log (10.3 MB)
sonar-OOM-Default.log (10.3 MB)

// Jemin

In all 3 log files the analysis crashes (and I find it odd how the analysis crashes – it doesn’t appear to be on actual analysis, but on detecting changed files)

Analyzing 360235 functions to detect bugs.

java.lang.OutOfMemoryError: Java heap space
Exception in thread "pool-4-thread-1" java.lang.OutOfMemoryError: Java heap space
Exception in thread "Daemon health stats" java.lang.OutOfMemoryError: Java heap space
3379 actionable tasks: 3062 executed, 4 from cache, 313 up-to-date
Error while receiving file changes
net.rubygrapefruit.platform.NativeException: Caught java.lang.OutOfMemoryError with message: Java heap space
	at net.rubygrapefruit.platform.internal.jni.AbstractNativeFileEventFunctions$NativeFileWatcher.executeRunLoop0(Native Method)
	at net.rubygrapefruit.platform.internal.jni.AbstractNativeFileEventFunctions$NativeFileWatcher.executeRunLoop(AbstractNativeFileEventFunctions.java:42)
	at net.rubygrapefruit.platform.internal.jni.AbstractFileEventFunctions$AbstractFileWatcher$1.run(AbstractFileEventFunctions.java:154)
Watched directory hierarchies: [C:\work\src-sonar\main]

I still don’t see how this could be linked to the JVM settings you have set server-side.

Did you try what I asked?

It would also be great to see a log from successful analysis, to see if it’s really the same (scope, etc.)