Maven JRE Provisioning vs. JAVA_HOME (and Java 25 journey)

We are running on a Sonarqube instance. We started to experiment with Java 25 and all was good, until we learned that sonar-maven-plugin provisions a JRE to run the scanner. Our pipeline agents had JDK 25 installed, but the provisioned version was … JDK 17.

I would imagine that, in rare cases, you wanted to provision a JDK that’s newer enough to run the compiled code. I think that it should be checked first if JAVA_HOME is set and if the Java executable cannot be found, provision a JRE. Or at least provision a JRE that is new enough. It feels like a bug to me.

Is there a way to override the default files returned by GET /analysis/jres endpoint?

After disabling the JRE provisioning, we were able to run it with Java 25, but I still think the JRE provisioning should happen as a fallback or make it an opt-in instead of having it enabled by default and having to opt-out.

Hi @silviuburceadev!

There’s actually no benefit to running the scanner with a higher version of Java—this won’t affect the analysis results. The analysis is powered by the Eclipse Compiler for Java (ECJ), which runs on Java 17, even when analyzing projects using newer Java versions. Any specifics related to the JVM that compiles the code are handled by the sonar.java.jdkHome property, which is set automatically by the Maven and Gradle scanners.

Our long-term goal is to eliminate the need for users to worry about which tool versions are installed. In the future, having a JVM preinstalled may not even be required at all.

The Java version for the Scanner version matters. Not directly for itself, but it matters more for the plugins used in analysis, e.g. FindBugs Sensor. Here are some of the logs for sonar:5.2.0.4988:sonar with the Java 17:

[INFO] Communicating with SonarQube Server 2025.4.3.113915
[INFO] JRE provisioning: os[linux], arch[x86_64]
[INFO] Starting SonarScanner Engine...
[INFO] Java 17.0.13 Eclipse Adoptium (64-bit)…
...
[INFO] Sensor FindBugs Sensor [findbugs]
[INFO] Findbugs plugin version: 4.6.0
[INFO] Loading findbugs plugin: /agent/_work/1/s/target/sonar/findbugs/sb-contrib.jar
[INFO] Loading findbugs plugin: /agent/_work/1/s/target/sonar/findbugs/findsecbugs-plugin.jar
[INFO] Findbugs output report: /agent/_work/1/s/target/sonar/findbugs-result.xml
[ERROR] [stderr] The following classes needed for analysis were missing:
[ERROR] [stderr]   java.lang.MatchException
[ERROR] [stderr]   java.lang.IO
[INFO] Sensor FindBugs Sensor [findbugs] (done) | time=10426ms

This is with JRE provisioning disabled:

[INFO] Communicating with SonarQube Server 2025.4.3.113915
[INFO] JRE provisioning is disabled
[INFO] Using the java executable '/usr/lib/jvm/temurin-25-jdk-amd64/bin/java' from JAVA_HOME
[INFO] SONAR_SCANNER_JAVA_OPTS=--sun-misc-unsafe-memory-access=allow
[INFO] Starting SonarScanner Engine...
[INFO] Java 25 Eclipse Adoptium (64-bit)
...
[INFO] Sensor FindBugs Sensor [findbugs]
[INFO] Findbugs plugin version: 4.6.0
[INFO] Loading findbugs plugin: /agent/_work/1/s/target/sonar/findbugs/sb-contrib.jar
[INFO] Loading findbugs plugin: /agent/_work/1/s/target/sonar/findbugs/findsecbugs-plugin.jar
[INFO] Findbugs output report: /agent/_work/1/s/target/sonar/findbugs-result.xml
[INFO] Sensor FindBugs Sensor [findbugs] (done) | time=11959ms

Notice how FindBugs Sensor reports errors for 2 missing classes, MatchException (since 21) and IO (since 25). It seems that it still finishes the analysis, but without covering (I think) the JDK features newer than Java 17. :frowning:

p.s. SONAR_SCANNER_JAVA_OPTS=--sun-misc-unsafe-memory-access=allow is not really relevant. We like to either handle the warnings/errors which can be handled, otherwise ignore them. Findbugs sensor’s Java version is something that can be handled.

Thank you for pointing that out!

On a positive note, we’ve added the ability to disable this feature at the instance level as of SonarQube v2025.5 (SONAR-25703). I’m a bit surprised it wasn’t backported to v2025.4 LTA—I’ll look into that.

Would this solution work for your needs? I understand that having to disable it per project can be tedious, but instance-level configuration should be more convenient.

1 Like

Disabling at instance level is even better! :slight_smile:

… but I’d still consider it a bug, if the provisioned JRE is a downgrade compared to the JDK used to run the Maven build. Can you log a ticket on my behalf? It seems I don’t have permissions to do that.

Hello @Colin,

How can I report the bug (or turn it into feature request) to have JRE provisioning with higher version than the JDK used by Maven build or provide custom JDKs at the instance level?

Thank you!

Hi,

What you’re looking for is the sonar.java.jdkHome property. I can’t guarantee that 3rd-party analyzers will use it properly, but it does allow you to sub-in a different JDK’s classes for native analysis than the JDK being used to run analysis.

 
HTH,
Ann

Hi Ann,

sonar.java.jdkHome doesn’t solve the JRE provisioning issue that I’ve run into for the Sonar Scanner with FindBugs sensor. I want to avoid a downgrade when JRE provisioning happens, which seems to be the default behavior right now. My guess is that the packed JREs of the Sonarqube instance would be the last LTS version and it wasn’t updated recently, from Java 17.

Hi,

It’s not clear to me what version you’re running, but the ticket Colin pointed two has been implemented in 2025.5 and 25.10. If sonar.java.jdkHome doesn’t meet your need (and if you can’t get the FindBugs crew to honor it :wink:) then I suggest you upgrade at your earliest convenience.

 
HTH,
Ann

Hi,

It is not about Sonarqube instance version here, as I think latest version still behaves the same (and will check it out myself to confirm it). It is also not about sonar.java.jdkHome being honored by FindBugs. It is the Sonar Scanner which provisions a JRE which overrides the JDK specified in sonar.java.jdkHome and is used as runtime for the actual scanning. This can lead to downgrades if the provisioned version is older. FindBugs actually behaves correctly, since the Sonar Scanner spins a child Java process with the provisioned version for scanning, which, again, can be older and leads to downgrades.

It is good that newer versions of Sonarqube can turn off the JRE provisioning at the instance level, which should be the default. If you need a different JRE to run the scanning, I’d say you know what you’re doing. Having this enabled by default sounds like Sonarqube knows better for you, which wasn’t really the case.

Maybe I’m misunderstanding what was the intention when JRE provisioning was added as a feature. Help me understand so we can reach a conclusion here.

Thanks,
Silviu

Hi Silviu,

The intention was that when we bump the minimum version of Java required to run the scanner, people don’t have to scramble to upgrade their vast CI estates.

 
HTH,
Ann