GC overhead Limit exceeded while running sonar runner

The problem

A common problem for someone who has recently set up SonarQube for code analysis. Specifically, the GC overhead limit exceeds for the projects having a mammoth code base. Memory is just not enough and the process goes for a toss and ultimately, it results in OutOfMemoryError.

Below is the stack trace that you might observe.

[code language=”plain”]
14:55:55.433 DEBUG – Release semaphore on project : org.sonar.api.resources.Project@5a7b5cb8[id=1,key=myProj_web,qualifier=TRK], with key batch-myProj_web
14:55:55.711 DEBUG – To prevent a memory leak, the JDBC Driver [com.mysql.jdbc.Driver] has been forcibly deregistered

INFO: ————————————————————————
INFO: EXECUTION FAILURE
INFO: ————————————————————————
Total time: 12:48.979s
Final Memory: 33M/910M
INFO: ————————————————————————
ERROR: Error during Sonar runner execution
org.sonar.runner.impl.RunnerException: Unable to execute Sonar
at org.sonar.runner.impl.BatchLauncher$1.delegateExecution(BatchLauncher.java:91)
at org.sonar.runner.impl.BatchLauncher$1.run(BatchLauncher.java:75)
at java.security.AccessController.doPrivileged(Native Method)
at org.sonar.runner.impl.BatchLauncher.doExecute(BatchLauncher.java:69)
at org.sonar.runner.impl.BatchLauncher.execute(BatchLauncher.java:50)
at org.sonar.runner.api.EmbeddedRunner.doExecute(EmbeddedRunner.java:102)
at org.sonar.runner.api.Runner.execute(Runner.java:100)
at org.sonar.runner.Main.executeTask(Main.java:70)
at org.sonar.runner.Main.execute(Main.java:59)
at org.sonar.runner.Main.main(Main.java:53)
Caused by: org.sonar.api.utils.SonarException: Can not execute Findbugs
at org.sonar.plugins.findbugs.FindbugsExecutor.execute(FindbugsExecutor.java:154)
at org.sonar.plugins.findbugs.FindbugsSensor.analyse(FindbugsSensor.java:59)
at org.sonar.batch.phases.SensorsExecutor.executeSensor(SensorsExecutor.java:79)
at org.sonar.batch.phases.SensorsExecutor.execute(SensorsExecutor.java:70)
at org.sonar.batch.phases.PhaseExecutor.execute(PhaseExecutor.java:131)
at org.sonar.batch.scan.ModuleScanContainer.doAfterStart(ModuleScanContainer.java:178)
at org.sonar.api.platform.ComponentContainer.startComponents(ComponentContainer.java:92)
at org.sonar.api.platform.ComponentContainer.execute(ComponentContainer.java:77)
at org.sonar.batch.scan.ProjectScanContainer.scan(ProjectScanContainer.java:199)
at org.sonar.batch.scan.ProjectScanContainer.scanRecursively(ProjectScanContainer.java:194)
at org.sonar.batch.scan.ProjectScanContainer.doAfterStart(ProjectScanContainer.java:187)
at org.sonar.api.platform.ComponentContainer.startComponents(ComponentContainer.java:92)
at org.sonar.api.platform.ComponentContainer.execute(ComponentContainer.java:77)
at org.sonar.batch.scan.ScanTask.scan(ScanTask.java:56)
at org.sonar.batch.scan.ScanTask.execute(ScanTask.java:44)
at org.sonar.batch.bootstrap.TaskContainer.doAfterStart(TaskContainer.java:82)
at org.sonar.api.platform.ComponentContainer.startComponents(ComponentContainer.java:92)
at org.sonar.api.platform.ComponentContainer.execute(ComponentContainer.java:77)
at org.sonar.batch.bootstrap.BootstrapContainer.executeTask(BootstrapContainer.java:175)
at org.sonar.batch.bootstrap.BootstrapContainer.doAfterStart(BootstrapContainer.java:163)
at org.sonar.api.platform.ComponentContainer.startComponents(ComponentContainer.java:92)
at org.sonar.api.platform.ComponentContainer.execute(ComponentContainer.java:77)
at org.sonar.batch.bootstrapper.Batch.startBatch(Batch.java:92)
at org.sonar.batch.bootstrapper.Batch.execute(Batch.java:74)
at org.sonar.runner.batch.IsolatedLauncher.execute(IsolatedLauncher.java:48)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.sonar.runner.impl.BatchLauncher$1.delegateExecution(BatchLauncher.java:87)
… 9 more
Caused by: java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError: GC overhead limit exceeded
at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:232)
at java.util.concurrent.FutureTask.get(FutureTask.java:91)
at org.sonar.plugins.findbugs.FindbugsExecutor.execute(FindbugsExecutor.java:146)
… 38 more
Caused by: java.lang.OutOfMemoryError: GC overhead limit exceeded
at edu.umd.cs.findbugs.util.Strings.escapeXml(Strings.java:167)
at edu.umd.cs.findbugs.xml.XMLAttributeList.getQuotedAttributeValue(XMLAttributeList.java:132)
at edu.umd.cs.findbugs.xml.XMLAttributeList.toString(XMLAttributeList.java:111)
at edu.umd.cs.findbugs.xml.OutputStreamXMLOutput.openTag(OutputStreamXMLOutput.java:112)
at edu.umd.cs.findbugs.SourceLineAnnotation.writeXML(SourceLineAnnotation.java:887)
at edu.umd.cs.findbugs.ClassAnnotation.writeXML(ClassAnnotation.java:192)
at edu.umd.cs.findbugs.BugInstance.writeXML(BugInstance.java:2292)
at edu.umd.cs.findbugs.SortedBugCollection.writeXML(SortedBugCollection.java:576)
at edu.umd.cs.findbugs.SortedBugCollection.writeXML(SortedBugCollection.java:497)
at edu.umd.cs.findbugs.XMLBugReporter.finish(XMLBugReporter.java:46)
at edu.umd.cs.findbugs.DelegatingBugReporter.finish(DelegatingBugReporter.java:81)
at edu.umd.cs.findbugs.DelegatingBugReporter.finish(DelegatingBugReporter.java:81)
at edu.umd.cs.findbugs.DelegatingBugReporter.finish(DelegatingBugReporter.java:81)
at edu.umd.cs.findbugs.FindBugs2.analyzeApplication(FindBugs2.java:1256)
at edu.umd.cs.findbugs.FindBugs2.execute(FindBugs2.java:282)
at org.sonar.plugins.findbugs.FindbugsExecutor$FindbugsTask.call(FindbugsExecutor.java:201)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
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)
[/code]

I had posted a question on StackOverFlow here but I couldn’t get any answers. I have observed this question was getting noticed and hence I decided to include the answer in this post.

The solution

Luckily, is possible to configure Sonar Qube through the “sonar.properties” file. This can be done per-project basis as the property file lies in the individual project directory. Modify the property file as below.

  1. Skip the package design analysis, sonar.skipPackageDesign=true
  2. Remove the entries for lib/test directory in your project’s properties file
  3. Give some more memory set SONAR_RUNNER_OPTS=-Xmx1536m -XX:MaxPermSize=512m
  4. Optionally you can disable design analysis by using sonar.skipDesign=true
  5. Restart SonarQube services and you should be good now đŸ™‚

Furthre reading

For the curious souls, below is the meaning of each property that we are setting.

  1. sonar.skipPackageDesign: Enabling this makes SonarQube analyse all of you source files to make sure they belong to the correct directory structure as mentioned by the source files package. This can be easily identified by most of the IDEs and hence, this analysis is not required. However, there are some cases (like the complete source file is commented out, including the package declaration) that cannot be easily identified. So be a little careful while toggling this flag.
  2. Remove the entries for lib/test: If you do not want to analyze the jars and the tests.
  3. SONAR_RUNNER_OPTS=-Xmx1536m -XX:MaxPermSize=512m: Giving some more room to SonarQube so that it can dance freely.
  4. sonar.skipDesign: It relates to the design plugin, which only analyzes project dependencies and modules.

For more reading, have a look at the SonarQube documentation.

Please note that in newer versions of SonarQube, some of the properties might be deprecated.