Force JDK/JRE for Sonar Scanner

We are attempting to transition from our existing SQ setup (7.6) to a new one (9.5). Our builds are Java builds targeting Java 8 using Gradle to orchestrate, running against a Java 8 JDK/JRE as specified in JAVA_HOME on our TeamCity build agents. The entire set of Gradle tasks (including the sonarqube task) is executed from a single entry point task, so the entire thing runs as a single Gradle process.

During our experiments we are running into the famous issue:

Caused by: java.lang.UnsupportedClassVersionError: org/sonar/batch/bootstrapper/EnvironmentInformation has been compiled by a more recent version of the Java Runtime (class file version 55.0), this version of the Java Runtime only recognizes class file versions up to 52.0 obviously because the entire process is running against the Java 8 JDK/JRE.

Because we invoke the sonarqube task as part of the entire build chain, the solution discussed in Moving Analysis to Java 11 | SonarQube Docs will not work for us, as we don’t invoke gradle separately for build vs analysis.

I tried simply updating the version of the SQ plugin we’re using to the latest, but that didn’t resolve the issue.

My question is:

Is it possible, using a SQ plugin config param, CLI argument, environment variable, or otherwise, to tell the sonar scanner to use a different JDK/JRE than the one the gradle process that calls the sonarqube task was invoked from?

As an aside, I find it interesting that this behavior appears when I change only the property and the sonar.login property; everything else is the same between my SQ 7.6 execution and my SQ 9.5 execution. Does the server send custom files back to the scanner to use?

Hi @BGreman ,

Welcome to Sonar Community :sonar:

Can you explain why you can’t separate build from analysis? Why not create a new step in your pipeline just for setting JAVA_HOME as Java11 and then run ./gradlew sonarqube?

This makes sense. Your build is robust enough to handle a large upgrade and SonarQube 9.0+ requires Java 11 for the scanner, so targeting a new SoanrQube version is all you did.

We run our builds through TeamCity, and if we were to separate the build from analysis into separate build steps, there are some gradle tasks that would be executed more than once unnecessarily (things like retrieving the version from TeamCity parameters so it’s available to the gradle process, etc). We used to have almost all the tasks as individual build steps in TeamCity but found that it was adding unnecessary time to our build pipeline and intentionally condensed them back down. This also made creating and maintaining new builds from a shared template much simpler.

Technically, separating build from analyze would make us actually have to run it in three phases: build, test (including SQ and Jacoco), and publish. Each of those phases would have some amount of gradle overhead that we avoid by having the entire set of tasks run in one gradle invocation.

It’s not impossible, just something we’re trying very hard to avoid reverting to just to support the needs of a single tool in our toolchain.

As for the robustness, my question was more around: When I run the sonarqube task, does the SQ server some files back to the CI build agent, and these are the ones that cannot be run against Java 8? Since we’re using the sonar-gradle-plugin, I would have assumed the scanner functionality would be the same no matter what SQ server version we were sending the analysis to but that’s clearly not the case.