开篇:代码检测遇 “黑天鹅”
在咱们日常用 SonarQube 给代码做 “体检” 的常规操作里,原本项目中的 SonarQube 和大多数项目一样,都乖乖用着 JDK8。在 GitLab CI 里,代码质量检测的配置也顺风顺水:
sonarqube_check:
stage: 代码质量检测
tags:
- sonar
image: $REGISTRY/devops/maven:3.6.3-openjdk-8-slim
variables:
SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar"
GIT_DEPTH: "0" # 告诉git获取所有的分支, 分析任务强制要求
cache:
key: "${CI_JOB_NAME}"
paths:
- .sonar/cache
script:
- mvn verify sonar:sonar -Dmaven.test.skip=false -Dsonar.host.url=${SONAR_HOST_URL} -Dsonar.login=${SONAR_LOGIN} -Dsonar.password=${SONAR_PASSWORD} -Dsonar.projectKey=${SVC_NAME} -Dsonar.projectVersion=${JAR_VERSION} -Dsonar.projectName=${SVC_NAME} -Dsonar.qualitygate.wait=true
when: manual #手动执行触发
allow_failure: false
谁能想到,AI 这股风一吹,领导一拍脑袋,想着用 AI 给代码扫描,一看 SonarQube 最新版有相关功能,链接在此https://docs.sonarsource.com/sonarqube-server/latest/ai-capabilities/overview/ ,没仔细调研就把部门的 SonarQube 升级到了 2025.1 版。这一升级,好家伙,问题来了!
问题大揭秘:JDK 版本 “掐架”
SonarQube 2025 是基于 JDK17 编译的,可咱还在用老配置扫描:
sonarqube_check:
stage: 代码质量检测
tags:
- sonar
image: $REGISTRY/devops/maven:3.6.3-openjdk-8-slim
variables:
SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar"
GIT_DEPTH: "0" # 告诉git获取所有的分支, 分析任务强制要求
cache:
key: "${CI_JOB_NAME}"
paths:
- .sonar/cache
script:
- mvn verify sonar:sonar -Dmaven.test.skip=false -Dsonar.host.url=${SONAR_HOST_URL} -Dsonar.login=${SONAR_LOGIN} -Dsonar.password=${SONAR_PASSWORD} -Dsonar.projectKey=${SVC_NAME} -Dsonar.projectVersion=${JAR_VERSION} -Dsonar.projectName=${SVC_NAME} -Dsonar.qualitygate.wait=true
when: manual #手动执行触发
allow_failure: false
结果报错了:
Failed to execute goal org.sonarsource.scanner.maven:sonar-maven-plugin:3.7.0.1746:sonar (default-cli) on project nisbos-api-gateway: Execution default-cli of goal org.sonarsource.scanner.maven:sonar-maven-plugin:3.7.0.1746:sonar failed: An API incompatibility was encountered while executing org.sonarsource.scanner.maven:sonar-maven-plugin:3.7.0.1746:sonar: java.lang.UnsupportedClassVersionError: org/sonar/batch/bootstrapper/EnvironmentInformation has been compiled by a more recent version of the Java Runtime (class file version 61.0), this version of the Java Runtime only recognizes class file versions up to 52.0
简单来说,就是 SonarQube 插件里的org.sonar.batch.bootstrapper.EnvironmentInformation类是用高版本 Java(对应 Java 17)编译的,咱当前的 Java 运行环境(Java 8)不认,这下代码扫描直接 “罢工” 了。
修复方案大比拼
- 升级 Java 版本
把 Java 运行时环境升级到和 SonarQube 插件匹配的版本,也就是 Java 17 或更高。比如把maven:3.6.3-openjdk-8-slim镜像升级成支持 JDK17 的镜像。但问题是,一堆历史遗留项目都是基于 JDK8 构建的,短期内改造,那成本和工作量,想想都头大。
2、降低 SonarQube 版本
理论上把 SonarQube 版本降回用 JDK8 的版本,问题就能解决。可现实是,SonarQube 现在和 AI 有点关联,你懂的,在团队里要推动降级,阻力重重。
3、构建与扫描 “分家”
把mvn sonar:sonar拆成两个流程,先基于 Maven 构建,再把构建好的物料送到 Sonar - Scanner 扫描。这个方案比较靠谱,具体脚本如下:
maven_deploy:
stage: 编译生成
only:
- branches
tags:
- sonar
image: $REGISTRY/devops/maven:3.6.3-openjdk-8-slim
script:
- mvn deploy -DskipTests -Dmaven.repo.local=/root/.m2/repository -s /root/.m2/settings-nisbos.xml
cache:
key: maven_target_cache
paths:
- $BUILD_TARGET_DIR
policy: push
when: manual #手动执行触发
allow_failure: false
sonarqube_check:
stage: 代码质量检测
only:
- branches
tags:
- sonar
image: $REGISTRY/sonarsource/sonar-scanner-cli:11.2.1.1844_7.0.2
variables:
SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar"
GIT_DEPTH: "0" # 告诉git获取所有的分支, 分析任务强制要求
script:
- sonar-scanner -Dsonar.java.binaries=$BUILD_TARGET_DIR -Dsonar.host.url=${SONAR_HOST_URL} -Dsonar.token=${SONAR_TOKEN} -Dsonar.projectKey=${SONAR_PROJECT_NAME} -Dsonar.projectVersion=${JAR_VERSION} -Dsonar.projectName=${SONAR_PROJECT_NAME} -Dsonar.qualitygate.wait=true
cache:
- key: maven_target_cache
paths:
- $BUILD_TARGET_DIR
policy: pull
- key: "${CI_JOB_NAME}"
paths:
- .sonar/cache
#when: manual #手动执行触发
allow_failure: false
总结:避坑指南与经验之谈
这篇主要讲了 SonarQube 和项目 JDK 版本不兼容,导致扫描失败的修复办法。其实官网也给了个解法,大概意思是:在某些情况下,要是分析的项目构建用的 Java 版本和执行分析时的 Java 版本不一样,像用 Java 17 运行分析,项目构建用 Java 11 或更早版本,就得手动设置sonar.java.jdkHome属性,指向合适的 JDK。比如分析 Java 11 项目:
# Here maven uses the default version of Java on the system but we specify that we want to analyze a Java 11 project.
mvn org.sonarsource.scanner.maven:sonar-maven-plugin:sonar \
# other analysis parameters
-Dsonar.java.jdkHome=/usr/lib/jvm/jdk11/
# other analysis parameters
但一开始我被误导了,这个属性只是让 SonarQube 分析器在分析代码时知道用哪个 JDK 的类,不是指定执行 Maven 和 SonarScanner 的 Java 版本,执行它们的 Java 版本还是由JAVA_HOME环境变量或者系统默认 Java 版本决定,所以官网这招解决不了我们的问题。
最终我们靠隔离关注点、遵循单一职责原则解决了问题。大家在遇到类似情况时,希望这篇文章能帮你少走弯路,赶紧解决问题!要是觉得有用,记得点赞、转发,让更多人看到,一起在代码的坑里 “互帮互助”!
共同學習,寫下你的評論
評論加載中...
作者其他優質文章