Bootstrap

静态代码扫描教程

静态代码扫描教程

工具概述

Sonarqube(Sonar)

地址:http://sonar.fxwork.kugou.net](http://sonar.fxwork.kugou.net)

Sonar(Sonar) 是一个开源平台,用于管理源代码的质量;Sonar 不只是一个质量数据报告工具,更是代码质量管理平台。支持的语言包括:Java、PHP、C#、C、Cobol、PL/SQL、Flex 等。

  • 代码覆盖:通过单元测试,将会显示哪行代码被选中
  • 改善编码规则
  • 搜寻编码规则:按照名字,插件,激活级别和类别进行查询
  • 项目搜寻:按照项目的名字进行查询
  • 对比数据:比较同一张表中的任何测量的趋势

这里的话,Sonar 作为静态扫码用途,那么什么是静态扫描呢?静态代码分析是指无需运行被测代码,仅通过分析或检查源程序的语法、结构、过程、接口等来检查程序的正确性,找出代码隐藏的错误和缺陷,如参数不匹配,有歧义的嵌套语句,错误的递归,非法计算,可能出现的空指针引用等等。

常见的 Java 静态代码扫描工具有,Checkstyle ,FindBugs ,PMD ,Jtest,Sonarqube(原名sonar),还是 facebook 开源的 Infer(Infer 只能在 Linux 和 Mac 上部署),目前来说 那边MTP 构建平台配置的是 JTest,这边Jenkins 配置的 Sonarqube,总的来说,Sonarqube 的效率,性能,误报率等方面会表现得更优秀一点。

这里是关于Sonarqube 的一个博客介绍: 静态代码扫描平台SonarQube简介

Jenkins

地址:Jenkins

Jenkins是一个功能强大的应用程序,允许持续集成和持续交付项目,无论用的是什么平台。这是一个免费的源代码,可以处理任何类型的构建或持续集成。集成Jenkins可以用于一些测试和部署技术。Jenkins是一种软件允许持续集成。

Jenkins 在静态代码扫描阶段,只负责构建的功能,大致的流程如下:

这里使用 Jenkins 作为自动构建平台还是有好处的,你可以在 Jenkins 配置构架触发器,然后定期执行构建或者条件触发构建(例如每提交一次代码就触发一次构建)

工作流程描述

操作流程

进行 Sonar 静态扫描的流程比较简单,只需要在 Jenkins 执行构建任务,然后去 Sonar 查看扫描结果,然后进行修改就好了;

数据分析页面说明

这里的错误类型比较多,简单进行一些说明,首先是根据严重程度(Severity)进行分类

  1. BLOCKER
    Bug with a high probability to impact the behavior of the application in production: memory leak, unclosed JDBC connection, … The code MUST be immediately fixed.

    这类bug是建议必须修复的,可能是高危bug很高可能性导致程序出错,例如会导致内存泄漏,JDBC 没关闭的 bug。

  2. CRITICAL
    Either a bug with a low probability to impact the behavior of the application in production or an issue which represents a security flaw: empty catch block, SQL injection, … The code MUST be immediately reviewed.

    这类bug是建议必须检查的,这类bug有较低的可能性导致程序出错,例如空的 Cache 语句块,SQL 注入语句;

  3. MAJOR
    Quality flaw which can highly impact the developer productivity: uncovered piece of code, duplicated blocks, unused parameters, …

    这类代码缺陷是建议检查的,有较高的可能性导致出错;例如,重复的代码块,未覆盖的代码

  4. MINOR
    Quality flaw which can slightly impact the developer productivity: lines should not be too long, “switch” statements should have at least 3 cases, …

    这类代码缺陷是轻微的,较低可能性

  5. INFONeither a bug nor a quality flaw, just a finding.

    连Warning 都不是,可能是bug或者缺陷

之后,你可以选择自己感兴趣的类型,勾选,这里是可以多重勾选的,会对你勾选的结果进行筛选。

关于修改Bug 一些技巧

通常来说,需要改的bug数目是比较大的,这里提供一些修改技巧;

  1. 首先要熟悉一下,缺陷和bug 的类型。

  2. 我们可以在右侧勾选Issues->Severity->Blocker,选中状态如下图,然后 crtl + 鼠标进入代码文件页面,注意观察侧边栏图标的不同,Blocker 类型是红色感叹号,你可以直接看这个就好了(图标类型参考下面 Issues 图标说明),点击这里的图标,能展开提示说明。

Sonar 教程

这里不介绍集成教程,只涉及配置和使用教程,主要是介绍和扩展目前繁星 jenkins 上的 Sonar 插件功能。

Sonar 功能面板说明

这里介绍的是Sonar 主面板上的功能;

主界面

主界面显示的各种项目集合和表格

Quality Gate

Quality Gate 的官方说明:http://docs.sonarqube.org/display/SONAR/Quality+Gates

这里简单的说明一下:

  1. Quality Gates 代码质量,这里的代码质量检查是根据设置的代码质量检测规范得出的结果,结果状态只有三种,具体看后面的描述;
  2. 代码质量检查规范在Sonar首页顶部Tab Quality Gates点击进入;

Quality Gates 结果

  • 通过(绿色勾勾)表示至少定义了一种质量门阀,而且没有质量问题超过门阀;
  • 警告(黄色感叹号)至少一个警告类型的质量门阀超过了上限,没有错误类型的质量门阀超过上限
  • 不通过(红色叉叉)错误类型的质量门阀超过了上限

手机Android项目的 Quality Gates 如下:

从这里可以看到,手机项目的质量检测,只关注 Blocker 选项

由于权限问题,我这边看不到 Sonar 设置

Blocker 类型总结

由于 Blocker 扫描出来的数目比较多,一般有几百个,然后

  • NullPointerException might be thrown as ‘XXXX’ is nullable here。某个对象可能为空,这类价值不大
  • Change this condition so that it does not always evaluate to “true”。某个条件一直为 true 或者false,这类价值也不大。
  • Catch Exception instead of Error. Exception 抛得太大,这类的话,能改就改
  • Close this “FileOutputStream”。文件流没有关闭,这类需要进行处理。
  • This class overrides “equals()” and should therefore also override “hashCode()”.。equals()方法和hashCode()方法总是同时的,为了实现深克隆~这个好像意义不大。
性能指标说明

你根据 Sonar 的扫描结果,进行了修改,那么怎样才能衡量出,你这个工作的意义所在?最表面的判断是Issues 减少了,但是,实际上性能和代码质量是否得到优化,我们又从何而知?

The More

静态扫描工具比较多,主流的工具在上面已经提到过了,下面我这里做一个简单的对比。

JTEST

官网地址: https://www.parasoft.com/product/jtest/

Jtest 是 Parasoft 公司推出的一款针对 Java 语言的自动化代码优化和测试工具,它通过自动化实现对 Java 应用程序的单元测试和编码规范校验,从而提高代码的可靠性以及 Java 软件开发团队的开发效率。

Android Lint

Lint 是 Android 很多 IDE 支持的一种静态代码检查工具,android lint 能够在不运行代码的前提下对源码和XML文件进行扫描找出可能潜在的优化点或者是错误方面,安全方面,性能方面,可行性方面等方面的提升。

Android 官方地址:Improve Your Code with Lint

我这里简单的进行了一些总结,包括介绍归纳以及使用方法。

介绍

android lint 静态代码检查是 SDK 自带的一种静态代码检查工具,在android studio 上得到了很好的支持,在as 2.0 版本以后支持自定义的 Lint 检查,方便定制自己的代码规范,在此之前只能通过 gradle 去运行自定义的 Lint 检查。

Android Lint作为一个是静态代码分析工具,它能够对你的Android项目中潜在的bug、可优化的代码、安全性、性能、可用性、可访问性、国际化等进行检查。

你可以在 setting-Inspections 查看当前的 Lint 设置。

比如我们可以看到 Lint 对XML文件进行的一个检查,Un ResolveID,也就是我们经常碰到的问题了,一个资源文件的ID找不到了,这类定义为 Error 级别,所以在我们运行之前,就会提示我们需要处理掉这个Error,不然的话,就没办法运行程序。

根据官方的介绍,lint 的检查流程图如下;

  • Application source files: 构成你Android project的源文件,包含Java和XML文件,图标,以及ProGuard配置文件。
  • lint.xml: 配置文件,用来指定你想禁用哪些lint检查功能,以及自定义问题严重度(problem severity levels)。
  • lint Tool: 一个可以从命令行或Android Studio中运行的静态打码扫描工具。
  • lint Output: lint检查的结果,可以在命令行中通过lint查看,也可以在Android Studio的Event Log中查看。

然后 Lint 主要可以发现以下问题(根据Google 2015 发布的说明,lint提供超过两百种类型的检查 ):

  • 缺少翻译(和未使用的翻译)
  • 布局性能问题(老的layoutopt工具会用于查找所有这样的问题,和除此之外更多的问题)
  • 未使用的资源
  • 不一致的数组大小(当在多个配置中定义数组)
  • 可访问性和国际化问题(硬编码字符串,缺少contentDescription等)
  • 图标问题 (如丢失密度、 重复图标、 错误尺寸等)
  • 可用性问题 (如不在文本字段上指定输入的类型)
  • 清单错误

简单的来说,上面提到的检查,那些是对一个项目有诱惑的,而且考虑什么时候进行 Lint 检查才是最合适的?我认为,在进入集成完成之后,可以进行一些资源,清单错误,图标问题的扫描;至于布局性能的扫描,可能要单独独立开来;也就是说,我们的develop分支,可能不进行上线前的 Lint 扫描和整理,新开一个 release-lint 分支进行Lint 扫描,问题解决。

使用方法

项目右键->Inspect->然后选择你需要检查的范围

我这里尝试检查过的项目,花费时间比较久(第一次使用Lint 需要下载一些Lint工具文件),大概需要20分钟,这里先看先Lint 检查的结果,然后看下 performance issues 和probable bug,这两个类型比较有意义。

进阶-自定义Lint

自定义Lint 是为了满足自己的开发,提高代码规范,在某些场景下,使用Lint能有效的避免一些问题,例如你是Library 的开发者,你需要对你的 API 使用者进行Lint检查,这样话 ,就能避免错误使用API的问题了。

Other
去除内容重复的图片资源文件(png,jpg,xml)

这个操作在实际开发中,也是有必要的,但是实施起来,确实异常的麻烦,会碰到以下问题:

  1. 我们新增加一个图片资源的时候,如何确定本身的 drawable 文件夹中,是否有这个图片;
  2. 同时,我们的 drawable 文件夹可能存在一模一样的图片,怎么去除;
  3. xml 文件重复的话,需要手动删除,比较麻烦

集成到 IDE 中

讲道理的话,Sonar 是可以集成到我们离线的 IDE 的,我的意思是将Sonar 测试结果发送到 IDE 上,然后我们可以轻松的在 IDE 上进行修改;当然了 Sonar 是支持 IDE 的联机检查的。

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;