查看: 269|回复: 0

几款好用的Android静态代码检查工具,附实践过程

[复制链接]

43

主题

43

帖子

139

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
139
发表于 2017-12-7 21:04:43 | 显示全部楼层 |阅读模式
1.介绍
本文主要介绍了Android的几种静态代码检查工具。它们分别从不同的角度来帮助我们检查代码的规范性,以便更好的规范我们的开发。最后给出代码检测实践。
2. Lint
Android Studio中提供的Android Lint是一款静态分析工具,通过它可以对Android工程源码进行静态代码分析,它能够检测出应用程序中的潜在漏洞以及其它可能被编译器所忽略的其它代码问题。Android Lint可以在以下几个层面分析代码:correctness正确性,security安全性,performance性能,usability可用性,accessibility可访问性和internationalization国际化。
2.1 Lint 配置
要查看和修改检查的问题严重界别的话,可以使用 File > Settings > Editor > Inspections 菜单来打开检查配置(Inspection Configuration )页,里面有一个支持检查项的清单。
2.2 Lint gradle配置
使用 Android Studio 的话, 你还可以针对特定的构建变量运行 Lint 检查, 或者也可以是来自 build.gradle 文件的所有变量。需要将 lintOptions 属性添加到构建文件的 android 设置中。下面这段代码来自于一个 Gradle 构建文件,它显示了如何将 quiet 选项设置成 true,将 abort 选项设置成 false。
android {lintOptions {// set to true to turn off analysis progress reporting by lintquiet true// if true, stop the gradle build if errors are foundabort false// if true, only report errorsignoreWarnings true}...}
2.3 Lint 运行检查
终端命令行
gradle lint
android studio 工具操作
Analyze > Inspect Code
2.4 Lint 检查结果如下
根据如下的检测结果进行对应的分析和修改
3. Checkstyle
Checkstyle是一款检查java程序代码样式的工具,可以有效的帮助我们检视代码以便更好的遵循代码编写标准,特别适用于小组开发时彼此间的样式规范和统一。Checkstyle提供了高可配置性,以便适用于各种代码规范。
Checkstyle具有很强的配置性.每一个checkstyle配置文件必须包含Checker作为根moduleTreeWalker module用来遍历java文件,并定义一些属性。ThreeWalker module包含了多个子module,用来进行检查规范。
3.1 检查规则
Checkstyle 规则配置遵循java 代码规范以及google代码规范,参考规则如下: Java官方代码规范 Google Java Style Checkstyle Configuration
Checkstyle能检测 Javadoc Comments(Javadoc相关)、Naming Conventions(命名惯例)、Headers(文件头检查)、Imports(导入检查)、Size Violations(检查大小)、Whitespace(空白相关)、Modifiers(修饰符相关)、Blocks(代码块)、Class Design(类设计)、Duplicates(重复)等等,更多规则见具体checksyle规则配置。
CheckStyle 规则配置例如:
<module name="Checker"> <module name="JavadocPackage"/> <module name="TreeWalker"> <module name="AvoidStarImport"/> <module name="ConstantName"/> <module name="EmptyBlock"/> </module></module>
3.2 插件安装
插件安装后,需要重新启动
3.3 使用
checkstyle gradle配置使用
def configDir = "${project.rootDir}/config/quality"def reportsDir = "${project.buildDir}/reports"task checkstyle(type: Checkstyle) { ignoreFailures = true configFile file("$configDir/checkstyle/checkstyle.xml") configProperties.checkstyleSuppressionsPath = file("$configDir/checkstyle/suppressions.xml").absolutePath source 'src' include '**/*.java' exclude '**/gen/**' classpath = files() reports { xml.enabled = true html.enabled = true } doLast { ant.xslt(in: reports.xml.destination, style: new File("$configDir/checkstyle/checkstyle-simple.xsl"), out: new File("$configDir", 'checkstyle.html')) }}
终端命令行执行 gradle checkstyle
4. Findbugs
Findbugs是一个静态分析工具,它检查类或者JAR 文件,将字节码与一组缺陷模式进行对比以发现可能的问题。Findbugs自带检测器,其中有60余种Bad practice,80余种Correctness,1种 Internationalization,12种Malicious code vulnerability,27种Multithreaded correctness,23种Performance,43种Dodgy。我们还可以自己配置检查规则(做哪些检查,不做哪些检查),也可以自己来实现独有的校验规则(用户自定义特定的bug模式需要继承它的接口,编写自己的校验类,属于高级技巧)。
Findbugs 也提供了 Android Studio 的插件支持,值得注意的是 Findbugs 分析的是 Java 字节码,所以在启用 Findbugs 之前要保证你的工程是编译过的,在 FIndbugs 扫描之后,如果发现问题,会在对应的代码出给出提示。
4.1 插件安装
类似于checksyle,在Android studio Setting -->plugins-->搜索findbugs。
4.2 使用
5. PMD代码审查
这个工具比较有趣:其实 PMD 真正的名字并不是 PMD 。 在其官方网站上你会发现两个非常有趣的名字: Pretty Much Done Project Meets Deadline 事实上 PMD 是一个非常强大的工具,它的作用类似 Findbugs,但是它的检测扫描是基于源码的,而且 PMD 不仅能检测 Java 语言,还能检测其他语言。PMD 的目标和 Findbugs非常的相似,都是通过定义的规则静态分析代码中可能出现的错误,为什么要同时使用 PMD 和 Findbugs呢?由于 Findbugs 和 PMD 的扫描方式不一样,PMD 能发现的一些 Findbugs 发现不了的问题,反之亦然。
PMD附带了许多可以直接使用的规则,利用这些规则可以找出Java源程序的许多问题,例如:
潜在的bug:空的try/catch/finally/switch语句
未使用的代码:未使用的局部变量、参数、私有方法等
可选的代码:String/StringBuffer的滥用
复杂的表达式:不必须的if语句、可以使用while循环完成的for循环
重复的代码:拷贝/粘贴代码意味着拷贝/粘贴bugs
循环体创建新对象:尽量不要再for或while循环体内实例化一个新对象
资源关闭:Connect,Result,Statement等使用之后确保关闭掉 此外,用户还可以自己定义规则,检查Java代码是否符合某些特定的编码规范。例如,你可以编写一个规则,要求PMD找出所有创建Thread和Socket对象的操作。
5.1插件安装
类似于checksyle,在Android studio Setting -->plugins-->搜索PMD。
5.2使用
5.3检测结果
6. 代码检测实践
6.1 检测工具的gradle配置
lint checkstyle pmd findbugs的gradle配置,统一写在quality.gradle 文件中,便于管理,配置如下:
apply plugin: 'checkstyle'apply plugin: 'findbugs'apply plugin: 'pmd'// Add checkstyle, findbugs, pmd and lint to the check task.check.dependsOn 'checkstyle', 'findbugs', 'pmd', 'lint'def configDir = "${project.rootDir}/config/quality"def reportsDir = "${project.buildDir}/reports"task checkstyle(type: Checkstyle) { ignoreFailures = true configFile file("$configDir/checkstyle/checkstyle.xml") configProperties.checkstyleSuppressionsPath = file("$configDir/checkstyle/suppressions.xml").absolutePath source 'src' include '**/*.java' exclude '**/gen/**' classpath = files() reports { xml.enabled = true html.enabled = true } doLast { ant.xslt(in: reports.xml.destination, style: new File("$configDir/checkstyle/checkstyle-simple.xsl"), out: new File("$configDir", 'checkstyle.html')) }}task findbugs(type: FindBugs, dependsOn: "assembleDebug") { ignoreFailures = true effort = "max" reportLevel = "high" excludeFilter = new File("$configDir/findbugs/findbugs-filter.xml") classes = files("${project.rootDir}/app/build/intermediates/classes") source 'src' include '**/*.java' exclude '**/gen/**' classpath = files() reports { xml.enabled true html.enabled = false xml.withMessages true } doLast { ant.xslt(in: reports.xml.destination, style: new File("$configDir/findbugs/fancy-hist.xsl"), out: new File("$configDir", 'findbugs.html')) }}task pmd(type: Pmd) { ignoreFailures = true ruleSetFiles = files("$configDir/pmd/pmd-ruleset.xml") ruleSets = [] source 'src' include '**/*.java' exclude '**/gen/**' classpath = files() reports { xml.enabled = true html.enabled = false } doLast { ant.xslt(in: reports.xml.destination, style: new File("$configDir/pmd/pmd-report-per-class.xslt"), out: new File("$configDir", 'pmd.html')) }}android { lintOptions { abort true xmlReport true htmlReport false lintConfig file("$configDir/lint/lint.xml") htmlOutput file("$reportsDir/lint/lint-result.html") xmlOutput file("$reportsDir/lint/lint-result.xml") }}
在app模块得gardle配置中,引用该配置:
apply from: '../config/quality.gradle'
6.2检测工具配置规则和报告样式
checkstyle checkstyle.xml 代码检测规则配置文件 checkstyle_simple.xml 代码检测报告样式文件 suppressions.xml 检测排除文件配置
findbugs findbugs-filter.xml 检测排除文件配置 fancy-hist.xsl 检测报告样式文件
lint lint.xml 检测规则
pmd pmd-ruleset.xml 检测规则 pmd-report-per-class.xslt 报告样式
6.3 Jenkins 配置和运行
Gradle 提供的方法,我们可以把四个工具的执行任务添加为 “check” task 的依赖:
check.dependsOn 'checkstyle', 'findbugs', 'pmd', 'lint'
现在,只要我们只想 “check” 这个 task ,Checkstyle、Windbags、PMD 和 Android Lint 都会自动执行。在 commit/push/merge request 之前 执行一下 check 任务,对我们代码质量的提高将是一种非常棒的方式。执行这个任务你可以在命令行中执行:gradlew check。Jenkins 中配置运行如下:
6.4 检测结果及分析
构建结果趋势图,正常情况下应该是逐渐收敛,表明代码越来越规范,越来越健壮。
点击左边任何一项可以查看详细得分析结果,分析结果分类别展示,可以按照包、文件、作者、错误类别、错误类型、警告、详细、新错误来进行分类查看分析。
7.修改不规范代码,使用小技巧
7.1 快捷键设置
快捷键可以在Settings -> Keymap 中查看和修改
7.2 Java和布局文件中的中文字符提取到资源文件中
查找中文字符串,以便提取到资源文件string.xml中,便于管理和国际化 Ctrl+ H 打开文件搜索,输入正则表达式 "[一-龥]{1,}",选择正则表达式搜索
layout 文件中string字符串,利用快捷键提取到资源文件中 聚焦到字符串,点击该行前面的灯泡,选择Extract Android String… 或者 快捷键 Alt +enter
java文件中 提取string 字符串 快捷键 Alt +enter
7.3 移除无用的资源
移除无用的资源 Refactor-->Remove Unused Resources...
查找无用资源 Analyze-->Run Inspection By Name 快捷键 Ctlr+Alt+Shift+i
7.4 查找和替换
Android Studio打开工程,选中项目,右键弹出选择框
查找 选择“Find in Path..” 或者快捷键 Ctrl+G
替换 选择“Replace in Path..” 或者快捷键 Alt+F

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表