【Jenkins使用之七】代码质量之静态代码分析

时间:2024-02-25 22:50:08

一、常用Java静态代码分析工具的分析与比较
Java 静态代码分析(static code analysis)工具能够在代码构建过程中帮助开发人员快速、有效的定位代码缺陷并及时纠正这些问题,从而极大地提高软件可靠性并节省软件开发和测试成本。
常用的有Checkstyle、FindBugs、PMD,他们各有侧重,目前PMD集成阿里的p3c比较流行。

 

1、PMD
PMD是一款采用BSD协议发布的Java程序代码检查工具。该工具可以做到检查Java代码中是否含有未使用的变量、是否含有空的抓取块、是否含有不必要的对象等。该软件功能强大,扫描效率高,是Java程序员debug的好帮手。
PMD附带了许多可以直接使用的规则,利用这些规则可以找出Java源程序的许多问题,常见的类型如下:

①潜在的bug:空的try/catch/finally/switch语句
②未使用的代码:未使用的局部变量、参数、私有方法等
③可选的代码:String/StringBuffer的滥用
④复杂的表达式:不必须的if语句、可以使用while循环完成的for循环
⑤重复的代码:拷贝/粘贴代码意味着拷贝/粘贴bugs
⑥循环体创建新对象:尽量不要再for或while循环体内实例化一个新对象
⑦资源关闭:Connect,Result,Statement等使用之后确保关闭掉

此外,用户还可以自己定义规则,检查Java代码是否符合某些特定的编码规范,如集成阿里的p3c。

参考:静态分析工具PMD

2、FindBugs

FindBug 是一款开源的 Java 代码检查工具,遵循 GNU 公共许可协议。它可以检查 Java 类或者 JAR 文件,运行的是 Java 字节码而不是源码,检查原理是:将字节码与一组缺陷模式进行对比来发现可能存在的问题,这些问题包括空指针引用、无限递归循环、死锁等。检查的 bug 类型包括:

Malicious code vulnerability:恶意代码
Dodgy code:不符合规范的代码
Internationalization:国际化相关问题,如错误的字符串转换;
Bad practice:坏的实践:常见代码错误,序列化错误,用于静态代码检查时进行缺陷模式匹配;
Multithreaded correctness:多线程的正确性:如多线程编程时常见的同步,线程调度问题;
Performance:运行时性能问题,如由变量定义,方法调用导致的代码低效问题。
Correctness:可能导致错误的代码,如空指针引用等;
Experimental:可能受到的恶意攻击,如访问权限修饰符的定义等;
Security:安全性

参考:

使用 FindBugs-IDEA 插件查找代码中潜在的 BUG

3、CheckStyle
CheckStyle作为检验代码规范的插件,除了可以使用配置默认给定的开发规范,如Sun的,Google的开发规范啊,也可以导入像阿里的开发规范的插件。事实上,每一个公司都存在不同的开发规范要求,所以大部分公司会给定自己的check规范,一般导入给定的checkstyle.xml文件即可实现。

 

Javadoc 注释:检查类及方法的 Javadoc 注释
命名约定:检查命名是否符合命名规范
标题:检查文件是否以某些行开头
Import 语句:检查 Import 语句是否符合定义规范
代码块大小,即检查类、方法等代码块的行数
空白:检查空白符,如 tab,回车符等
修饰符:修饰符号的检查,如修饰符的定义顺序
块:检查是否有空块或无效块
代码问题:检查重复代码,条件判断,魔数等问题
类设计:检查类的定义是否符合规范,如构造函数的定义等问题

参考:

CheckStyle使用

Eclipse中安装和使用CheckStyle

 

4、区别

参考:

常用Java静态代码分析工具的分析与比较

代码质量检测工具FindBugs、PMD和CheckStyle对比

二、静态代码分析插件集成
通常这些工具都会提供IDE插件、maven插件、jenkins插件、sonarQube插件。
也就是说Checkstyle、FindBugs、PMD有:
  针对于开发人员本机的代码检查使用的Eclipse、Idea都有对应的插件;
  针对于构建jenkins、maven也有对应的插件,可以生成测试报告,用于自动化构建,避免开发人员不进行本机检查就上传代码的情况(sonarQube出来之前就是使用maven来生成报告);
  针对于sonarQube代码管理平台既可以用于开发人员检查代码,也可以集成到自动化构建平台生成检查报告。
注意:为方便在后面的自动化构建中统一,在一个project中事务开发、自动化构建等环节要使用同一种分析工具。

公司里一般涉及两个环节:

1、开发环节

1)开发人员要求使用统一 的IDE(eclipse、Idea),然后安装统一的静态代码检查工具:比如checkStyle检查公司要求的代码规范、PMD或findbugs检查潜在问题代码;

2)当开发人员开发完成功能后,使用这些IDE集成插件检查代码,并修正插件检测出来的问题;

3)将代码提交的版本库(git或者svn);

2、自动构建环节

公司每天进行代码的全量构建,jenkins要事先安装相应的Checkstyle、FindBugs、PMD插件:

1)jenkins从版本库主干或分支拉取源代码;

2)使用maven插件编译;

3)通过maven调用Checkstyle、FindBugs、PMD插件代码检查,如果检测出来相应问题 则构建失败,并将问题、问题代码提交人发邮件通知相关人员修改。

以上两个环节出了使用这些插件以外,目前是使用sonarQube代码质量管理平台来检查,sonarQube除了有自身的检查规则以外,也可以集成Checkstyle、FindBugs、PMD插件,然后生成检查报告。

参考:

eclipse集成阿里代码规范工具p3c

Eclipse中安装和使用CheckStyle

Eclipse 安装FindBugs插件

Jenkins下配置findbugs、pmd及checkstyle实现代码自动检测 

三、SonarQube

SonarQube是一个代码质量数据报告工具,也是代码质量管理平台,相对于Checkstyle、FindBugs、PMD,有更加优秀的图形化界面,以及可以查询出其它软件难以定位到的问题。

SonarQube可以从以下七个维度检测代码质量:

(1)不遵循代码标准:SonarQube可以通过PMD,CheckStyle,Findbugs等等代码规则检测工具规范代码编写。
(2)潜在的缺陷:SonarQube可以通过PMD,CheckStyle,Findbugs等等代码规则检测工具检 测出潜在的缺陷。
(3)糟糕的复杂度分布:文件、类、方法等,如果复杂度过高将难以改变,这会使得开发人员 难以理解它们, 且如果没有自动化的单元测试,对于程序中的任何组件的改变都将可能导致需要全面的回归测试。
(4)重复:显然程序中包含大量复制粘贴的代码是质量低下的,sonar可以展示 源码中重复严重的地方。
(5)注释不足或者过多:没有注释将使代码可读性变差,特别是当不可避免地出现人员变动 时,程序的可读性将大幅下降 而过多的注释又会使得开发人员将精力过多地花费在阅读注释上,亦违背初衷。
(6)缺乏单元测试:SonarQube可以很方便地统计并展示单元测试覆盖率。
(7)糟糕的设计:通过SonarQube可以找出循环,展示包与包、类与类之间的相互依赖关系,可以检测自定义的架构规则 通过sonar可以管理第三方的jar包,可以利用LCOM4检测单个任务规则的应用情况, 检测藕合。

1、SonarQube安装
SonarQube是一个平台,要部署一个专门的Server应用,然后通过界面来管理和查看。SonarQube服务器主要包括web服务器,基于ElasticSearch的搜索服务器,计算引擎服务器。其中,web服务器,是供开发人员浏览查看代码分析结果,进行相应的配置等。计算引擎服务器主要是处理代码分析报表并将其存储在数据库。SonarQube数据库用来存储配置信息和代码分析报表。

关于SonarQube没有权威的书籍,只能查看官网文档:https://docs.sonarqube.org/   选择相应版本查看就可以了。

(1)关于安装jdk、mysql、maven版本

jdk:jdk1.8
mysql:要求>=5.6 && < 8.0,默认是H2 embbed 内存类型数据库,用来保存元数据信息,为了长期管理肯定要用持久化数据库,这里选用mysql,当然也可以选择其他的。
maven:3.6.3

(2)下载SonarQube CE版本(其他版本收费):http://www.sonarqube.org/downloads/
SonarQube-7.8依赖Java 8,且支持mysql管理元数据的最后版本,以后的版本需要jdk11且不支持mysql 管理配置元数据。

(3)解压
[root@node106 src]# unzip sonarqube-7.8.zip -d /usr/local

(4)配置
修改为mysql数据库,url是数据库连接地址,username是数据库用户名,jdbc.password是数据库密码,login是sonarqube的登录名,sonar.password是sonarqube的密码

[root@node106 conf]# vim /usr/local/sonarqube-7.8/conf/sonar.properties
sonar.jdbc.url=jdbc:mysql://192.168.0.141:3306/qjfsonar?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useConfigs=maxPerformance
sonar.jdbc.username=gmsd
sonar.jdbc.password=gmsdtrade
sonar.sorceEncoding=UTF-8
sonar.login=admin
sonar.password=admin

(5)启动

#默认端口sonar.web.port=9000 可以修改

[root@node106 linux-x86-64]# /usr/local/sonarqube-7.8/bin/linux-x86-64/sonar.sh start
Starting SonarQube...
Started SonarQube.

报错:

1)、org.elasticsearch.bootstrap.StartupException: java.lang.RuntimeException: can not run elasticsearch as root
sonarqube里面有elasticsearch组件,ES不允许使用root启动,新建普通用户启动。

2)、[2] bootstrap checks failed
[1]: max file descriptors [4096] for elasticsearch process is too low, increase to at least [65535]
[2]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
修改/etc/security/limits.conf 后面追加如下内容:

[root@node106 conf]# vim /etc/security/limits.conf
* soft nofile 65536
* hard nofile 65536
* soft memlock unlimited
* hard memlock unlimited

 

3)、[1] bootstrap checks failed
[1]: max virtual memory areas vm.max_map_count [65536] is too low, increase to at least [262144]

#修改/etc/sysctl.conf
[root@node106 logs]# vim /etc/sysctl.conf
[root@node106 logs]# sysctl -p
vm.max_map_count = 655360

#注意修改后重新登录 才能生效

4)、java.lang.IllegalStateException: Fail to connect to database
修改mysql允许sonarQube所在的主机访问
grant all privileges on *.* to root@\'%\' identified by "123456";

完全启动需要较长时间:

 

(6)安装中文插件
进入Marketplace查找插件 并进行install

目前插件市场里提供匹配最新8.4版本的汉化插件,和我安装的7.8版本不匹配,install时会报错:

我们要下载7.8 对应版本中文插件 sonar-l10n-zh-plugin-1.28.jar,地址:https://github.com/SonarQubeCommunity/sonar-l10n-zh/releases
然后放入 sonarqube-7.8/extensions/plugins 目录

[root@node106 plugins]# pwd
/usr/local/sonarqube-7.8/extensions/plugins
[root@node106 plugins]# ll
total 88032
-rw-r--r-- 1 sonar sonar 224 Jun 17 2019 README.txt
-rw-r--r-- 1 sonar sonar 287504 Jun 17 2019 sonar-auth-github-plugin-1.5.0.870.jar
-rw-r--r-- 1 sonar sonar 3388540 Jun 17 2019 sonar-auth-saml-plugin-1.1.0.181.jar
-rw-r--r-- 1 sonar sonar 4092977 Jun 17 2019 sonar-csharp-plugin-7.14.0.8411.jar
-rw-r--r-- 1 sonar sonar 7016445 Jun 17 2019 sonar-css-plugin-1.1.0.993.jar
-rw-r--r-- 1 sonar sonar 1551459 Jun 17 2019 sonar-flex-plugin-2.4.0.1222.jar
-rw-r--r-- 1 sonar sonar 3903342 Jun 17 2019 sonar-go-plugin-1.1.1.2000.jar
-rw-r--r-- 1 sonar sonar 1727846 Jun 17 2019 sonar-html-plugin-3.1.0.1615.jar
-rw-r--r-- 1 sonar sonar 14629 Jun 17 2019 sonar-jacoco-plugin-1.0.1.143.jar
-rw-r--r-- 1 sonar sonar 8302512 Jun 17 2019 sonar-java-plugin-5.13.0.18197.jar
-rw-r--r-- 1 sonar sonar 6866969 Jun 17 2019 sonar-javascript-plugin-5.2.1.7778.jar
-rw-r--r-- 1 sonar sonar 7595999 Jun 17 2019 sonar-kotlin-plugin-1.5.0.315.jar
-rw-r--r-- 1 sonar sonar 47581 Sep 8 09:53 sonar-l10n-zh-plugin-1.28.jar
-rw-r--r-- 1 sonar sonar 300503 Jun 17 2019 sonar-ldap-plugin-2.2.0.608.jar
-rw-r--r-- 1 sonar sonar 5107348 Jun 17 2019 sonar-php-plugin-3.1.1.4762.jar
-rw-r--r-- 1 sonar sonar 2752193 Jun 17 2019 sonar-python-plugin-1.14.0.3086.jar
-rw-r--r-- 1 sonar sonar 10036210 Jun 17 2019 sonar-ruby-plugin-1.5.0.315.jar
-rw-r--r-- 1 sonar sonar 9202024 Jun 17 2019 sonar-scala-plugin-1.5.0.315.jar
-rw-r--r-- 1 sonar sonar 2622236 Jun 17 2019 sonar-scm-git-plugin-1.8.0.1574.jar
-rw-r--r-- 1 sonar sonar 7229293 Jun 17 2019 sonar-scm-svn-plugin-1.9.0.1295.jar
-rw-r--r-- 1 sonar sonar 2239156 Jun 17 2019 sonar-typescript-plugin-1.9.0.3766.jar
-rw-r--r-- 1 sonar sonar 3576923 Jun 17 2019 sonar-vbnet-plugin-7.14.0.8411.jar
-rw-r--r-- 1 sonar sonar 2242738 Jun 17 2019 sonar-xml-plugin-2.0.1.2020.jar

安装完成后需要重启sonarQube:

 

2、客户端

参见官网:Analyzing Source Code
SonarQube按照代码是否在本地还是托管分为本地分析和远程分析:

  本地分析对应的客户端常用有三种:sonar-scanner、使用maven(gradle)插件、使用IDE插件sonarLint,另还有Ant Task 现在用的少了。

  远程分析对应客户端是集成到jenkins里的sonar-scanner插件;

(一)本地分析

第一种客户端:sonar-scanner方式

SonarQube为代码检查的server,并提供可视化界面;sonar-scanner为client,进行分析并将分析报告并且发送到server中,也就是传统的C/S关系。

 

使用场景除了java、C++以外,其他语言scala,python,php或者一个项目使用多种语言时通过以下方式使用sonar-scanner(下载地址:https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/),这里使用sonar-scanner-cli-4.2.0.1873-windows.zip。在sonar-scanner早期版本叫sonar-runner注意版本太低会报错:Fail to download libraries from server。

示例拓扑:
这里我们将SonarQube服务端安装在192.168.118.106 linux上,然后将sonar-scanner安装在192.168.0.141 win7上,然后使用sonar-scanner扫描win7上工程E:\srcs\mybatis-3-mybatis-3.5.4里的代码。
(1)解压sonar-scanner-cli-4.2.0.1873-windows.zip

(2)配置 连接SonarQube同一个数据库 D:\sonar-scanner-cli-4.2.0.1873\conf\sonar-runner.properties

#Configure here general information about the environment, such as SonarQube server connection details for example
#No information about specific project should appear here

#----- Default SonarQube server  SonarQube服务端
sonar.host.url=http://192.168.118.106:9000
#----- Default source code encoding
sonar.sourceEncoding=UTF-8

(3)设置环境变量


(4)示例工程mybatis-3-mybatis-3.5.4
在要进行代码分析的项目根目录下,新建sonar-project.properties文件

#----- Global database settings (not used for SonarQube 5.2+)  数据库用户和密码
sonar.jdbc.username=root
sonar.jdbc.password=123456
#----- MySQL  mysql数据库连接  要和SonarQube服务端使用同一个数据库
sonar.jdbc.url=jdbc:mysql://192.168.0.141:3306/sonar?useUnicode=true&amp;characterEncoding=utf8
sonar.login=admin
sonar.password=admin

# 项目key 保证唯一
sonar.projectKey=mybatis-3-mybatis-3.5.4
# 项目名字
sonar.projectName=mybatis-3-mybatis-3.5.4
sonar.projectVersion=3.5.4
sonar.language=java
sonar.modules=java-module

# sonar.sources是源文件所在的目录 注意如果下面还有css文件会要求安装Node.js
java-module.sonar.sources=src/main/java
java-module.sonar.projectBaseDir=.
# 指定class目录 从sonarQube 4.12开始,sonar将会进行程序的动态检查,不配置sonar.java.binaries属性将会出错
sonar.java.binaries=target/classes
# Encoding of the source code. Default is default system encoding
#sonar.sourceEncoding=UTF-8

(5)然后在该目录下打开命令运行窗口,执行sonar-scanner命令,分析成功之后显示如下:

到sonarQube界面查看

第二种方式:使用maven、gradle扫描方式
这里展示使用maven两种整合方式,前提项目是maven项目。

(1)修改$MAVEN_HOME/conf/settings.xml

<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">

  <localRepository>E:\workspace\repository</localRepository>
  
  <pluginGroups>
    <pluginGroup>org.sonarsource.scanner.maven</pluginGroup>
  </pluginGroups>

  <proxies>
  </proxies>
  
  <servers>
    <server>
    <id>releases</id>
    <username>admin</username>
    <password>Aa123456</password>
    </server>
    <server>
    <id>snapshots</id>
    <username>admin</username>
    <password>Aa123456</password>
    </server>
  </servers>

  <mirrors>
    <mirror>
        <id>alimaven</id>
        <name>aliyun maven</name>
        <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
        <mirrorOf>central</mirrorOf>
    </mirror>
  </mirrors>

  <profiles>
        <profile>
            <id>sonar</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <properties>
                <sonar.host.url>
                  http://192.168.118.106:9000
                </sonar.host.url>
            </properties>
        </profile>
  </profiles>
</settings>

 

(2)到Maven项目的根目录执行如下命令,即可使用SonarQube分析项目
方式一:直接在含有pom.xml的目录执行分析

mvn clean verify sonar:sonar -Dmaven.test.skip=true

方式二:多模块情况下 先执行install 确保代码最新

mvn clean install -Dmaven.test.skip=true

#然后执行分析 注意需要添加-Dsonar.java.binaries参数

mvn sonar:sonar

方式三:指定sonar的插件版本

mvn org.sonarsource.scanner.maven:sonar-maven-plugin:3.6.0.1398:sonar

建议可以在项目的pom.xml指定sonar-maven-plugin插件版本

<build>
  <pluginManagement>
    <plugins>
      <plugin>
        <groupId>org.sonarsource.scanner.maven</groupId>
        <artifactId>sonar-maven-plugin</artifactId>
        <version>3.6.0.1398</version>
      </plugin>
    </plugins>
  </pluginManagement>
</build>

第三中方式:使用IDE插件sonarLint

这里以idea使用sonarLint举例,注意这种方式检查报告旨在idea里查看,sonaQube里看不到

(1)安装插件

插件里搜索sonarLint 然后install

使用方式(一)

(2)sonarLint全局配置 配置sonarQube服务器

(3)项目设置

SonarLint-->Project Setting配置选项卡中配置项目信息,勾选Binding project to  SonarQube / SonarCloud,在Connection下拉框中选中刚刚配置好的服务链接,在project选项中点击Search in list选择相应的项目,点击OK;

注意这种方式是查询工程下面有sonar-project.properties的工程

(4)扫描后查看报告

使用方式(二)

(1)在需要进行代码分析的项目上点击右键,依次选择:AnaLyze—> AnaLyze with SonarLint(或者再SonarLint报告选项卡中点击AnaLyze All Project Files图标)在弹出对话框中点击Preceed,等待项目代码分析完毕;
(2)代码分析完毕后,在“SonarQube Report”选项卡中会显示代码分析结果,可对单个文件展开,显示该文件中的各个问题,单击某一条结果,可在右侧Rule选项卡中看到对问题的详细描述,双击某一条记录,可以快速跳转至该条结果对应的代码的位置;
(3)SonarLint插件默认是自动进行代码检查,但是为了保证代码检查结果的实时性和有效性,在每完成一定数量的代码以后,我们就对代码进行分析。

 (二)远程分析-整合jenkins

 

3、界面使用教程

参考:SonarQube使用介绍

 

sonarQube参考:

官网文档
eclipse安装sonarLint插件

SonarQube的安装、配置与使用

SonarQube7.3安装和使用说明

sonarqube简介+架构+搭建+不同语言详细用法