Android 静态代码分析
在一些大型项目中,静态代码分析是必不可少的,通过静态代码分析可以避免一些低级的问题,与此同时可以规范代码书写、提高代码质量。本文主要介绍4种分析工具(CheckStyle、Findbugs、PMD、Android Lint)和如何快速接入。
功能介绍
CheckStyle
CheckStyle 主要的功能就是实时检测,代码的规范(Code Style)是否符合我们规定的一个模板,如定义的静态常量是大写,
局部参数以m开头,函数名字不超过20个字等。当发现这些不符合这些规范时,它就报一个警告或者错误等提示。
CheckStyle 检验的主要内容包括Javadoc注释、命名约定、标题、Import 语句、体积大小、空白、修饰符、块、代码问题、类设计和混合检查。它的功能比较丰富,相对配置起来比较复杂,需要根据自己的需求配置想要检查的内容。在 Android 项目中使用了Android Studio它集成了 IDEA 的拓展特性,它也拥有 CheckStyle 的插件,在 Android 项目中,使用的 Gradle 配置。
Findbugs
Findbugs 主要的功能是使用静态分析来检测 java 字节码中发现的错误。所以它分析的是程序的字节码,它不仅可以检测出一些普遍的错误,也可以检测由于对语言特性误解而产生的错误。由于 FindBugs 分析代码字节码,所以至少需要编译一次代码才能够进行检查。
Findbugs 检验的主要内容包括找出 hash equals 不匹配、Null 指针对 null 的解引用(dereference)和冗余比较、初始化之前读取字段等问题。此外,用户还可以自己定义规则。在 Android Studio 中开发 Android 项目时利用 findbugs 插件可以找到潜在的很多问题,避免上线后才发现这些低级的问题,findbugs 插件可以为这些 bug 定义等级,发布到控制台,方便开发者逐一解决
PMD
PMD 主要的功能就是通过静态分析获知代码错误。也就是说,在不运行 Java 程序的情况下报告错误。它跟 Findbugs 类似,但是它不是检测字节码,它是直接检测源代码。
PMD 检验的主要内容包括潜在的bug:空的 try/catch/finally/switch 语句,未使用的代码:未使用的局部变量、参数、私有方法等,可选的代码:String/StringBuffer的滥用,复杂的表达式:不必须的if语句、可以使用 while 循环完成的 for 循环,重复的代码:拷贝/粘贴代码意味着拷贝/粘贴 bugs,循环体创建新对象:尽量不要再 for 或 while 循环体内实例化一个新对象,资源关闭:Connect,Result,Statement等使用之后确保关闭掉等问题。此外,用户还可以自己定义规则,检查Java代码是否符合某些特定的编码规范。同样在在 Android Studio 有 PMD 插件,利用 PMD 插件可以简单直观的发现 bug。
Android Lint
Android Lint主要的功能它可以检测Android项目源文件中潜在的bug,也可以在正确性、安全性、性能、可用性、可访问性和国际化等方面进行优化。Android Lint是一个静态的代码分析工具。
Android Lint检验的主要内容包括布局性能(以前是 layoutopt工具,可以解决无用布局、嵌套太多、布局太多)、未使用到资源、不一致的数组大小、国际化问题(硬编码)、图标的问题(重复的图标,错误的大小)、可用性问题(如不指定的文本字段的输入型)、manifest文件的错误等问题。在使用时需要在gradle文件中的进行配置。
快速接入
下载config.zip,解压后看下目录结构
下载链接:http://download.youkuaiyun.com/detail/u010420435/9806992
quality.gradle 文件主要定义了4种检查工具的 gradle task ,每个 task 则分别定义了检查规则、忽略条件以及检查路径、输出报告格式等内容。代码如下
//引入插件
apply plugin: 'checkstyle'
apply plugin: 'findbugs'
apply plugin: 'pmd'
//将 checkstyle, findbugs, pmd 和 lint 加入到 gradle check task 中
check.dependsOn 'checkstyle', 'findbugs', 'pmd', 'lint'
task checkstyle(type: Checkstyle) {
configFile file("${project.rootDir}/config/quality/checkstyle/square-picasso-checkstyle.xml")//指定规则
configProperties.checkstyleSuppressionsPath =file("${project.rootDir}/config/quality/checkstyle/suppressions.xml").absolutePath
source 'src'
include '**/*.java'
exclude '**/gen/**'
classpath = files()}
task findbugs(type: FindBugs, dependsOn: assembleDebug) {
ignoreFailures = false
effort = "max"
reportLevel = "high"
excludeFilter = new File("${project.rootDir}/config/quality/findbugs/findbugs-filter.xml")//配置过滤文件
classes = files("${project.rootDir}/你要测试的项目名/build/intermediates/classes")
source 'src'
include '**/*.java'
exclude '**/gen/**'
reports {
xml.enabled = false
html.enabled = true
xml {
destination "$project.buildDir/reports/findbugs/findbugs.xml"//配置report输出路径
}
html {
destination "$project.buildDir/reports/findbugs/findbugs.html"//配置report输出路径
}
}
classpath = files()
}
task pmd(type: Pmd) {
ignoreFailures = false
ruleSetFiles = files("${project.rootDir}/config/quality/pmd/pmd-ruleset.xml")
ruleSets = []
source 'src'
include '**/*.java'
exclude '**/gen/**'
reports {
xml.enabled = false
html.enabled = true
xml {
destination "$project.buildDir/reports/pmd/pmd.xml"
}
html {
destination "$project.buildDir/reports/pmd/pmd.html"
}
}
}
android {
lintOptions {
abortOnError true
xmlReport false
htmlReport true
lintConfig file("${project.rootDir}/config/quality/lint/lint.xml")
htmlOutput file("$project.buildDir/reports/lint/lint-result.html")
xmlOutput file("$project.buildDir/reports/lint/lint-result.xml")
}
}
checkstyle.xml 文件定义了checkstyle 的检查规则,suppressions.xml定义了忽略条件
findbugs-filter.xml 文件定义了过滤规则
lint.xml 文件定义了Android lint 的规则
pmd-ruleset.xml 文件定义了pmd 的检查规则集
将解压后的 config 文件夹放到 Android Studio 项目的根目录,然后在你要进行静态代码分析的项目中gradle文件加入如下代码
apply from: '../config/quality.gradle'
至此,引入过程已经结束。
开始执行
执行方式有两种
1.直接执行更目录 gradle check task ,执行这个 task 可以一次性把4种检查全部执行一遍
2.分布执行
在测试项目的 gradle task 找到 checksytle、pmd、findbugs 的 task 双击执行即可如下图
执行结束后测试报告会在你项目的 /build/reports 目录下生成
参考链接:http://blog.youkuaiyun.com/hp910315/article/details/48809935