Error-prone,Google出品的Java和Android Bug分析利器

是什么

  • 静态的Java和Android bug分析利器
  • 由Google出品
  • 由error-prone接管compiler,在代码编译时进行检查,并抛出错误中断执行
  • 在抛出错误的同时给出具体的原因和相应方案
  • error-prone github 地址为 https://github.com/google/error-prone

举几个例子

1 2 3 4 5

private void testCollectionIncompatibleType() { Set<Short> set = new HashSet<>(); set.add(Short.valueOf("1")); set.remove(0); }

上面的代码中

  • set是一个接受Short类型的集合
  • 我们想通过类似从List.remove(index)方式删除一个元素
  • 但是Set没有remove(index)方法,有的只是remove(Object)方法,普通编译器不会报错,而error-prone则会发现

报出的错误信息为

1 2 3 4 5

/Users/jishuxiaoheiwu/github/ErrorProneSample/app/src/main/java/com/example/jishuxiaoheiwu/errorpronesample/MainActivity.java:24: error: [CollectionIncompatibleType] Argument '0' should not be passed to this method; its type int is not compatible with its collection's type argument Short set.remove(0); ^ (see http://errorprone.info/bugpattern/CollectionIncompatibleType)

再举一个例子

1

"hello World".getBytes().toString();

报出的错误是

1 2 3 4 5

/Users/jishuxiaoheiwu/github/ErrorProneSample/app/src/main/java/com/example/jishuxiaoheiwu/errorpronesample/MainActivity.java:16: error: [ArrayToString] Calling toString on an array does not provide useful information "hello World".getBytes().toString(); ^ (see http://errorprone.info/bugpattern/ArrayToString)

提示上面的byte[].toString()方法打印没有有用信息。

BugPattern

Error-prone是基于BugPattern来发现问题的,覆盖范围不仅限于Java还包含Android代码。一些比较常见的BugPattern有如下这些

  • ArrayToString 直接调用数组的toString方法打印不出有用信息
  • DivZero 0不能做除数,即分母
  • DefaultCharset 调用系统默认的Charset
  • MissingDefault switch中缺少default
  • MislabeledAndroidString Android中的字符串命名和内容不匹配,具有误导性
  • HardCodedSdCardPath 硬编码sd卡路径
  • IsLoggableTagLength log tag字符数量过长
  • 其他
  • 更多的bug pattern请参考 bugpatterns

BugPattern有三种严重程度,如下

  • ERROR
  • WARNING
  • SUGGESTION

只有ERROR的严重程度才会中断当前的编译,其他情况都会以日志输出形式展现。

如何配置

error-prone有对应的gradle插件,只需要应用即可。需要的操作很简单,只需要三步

  • 增加相应的maven repo
  • 在依赖中设置error-prone plugin classpath
  • 应用error-prone plugin

一个完整的代码示例如下,修改的文件为Project的build.gradle文件

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24

buildscript { repositories { jcenter() // error-prone相关配置 maven { url "https://plugins.gradle.org/m2/" } } dependencies { classpath 'com.android.tools.build:gradle:2.2.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files // error-prone相关配置 classpath "net.ltgt.gradle:gradle-errorprone-plugin:0.0.9" } } allprojects { repositories { jcenter() } //error-prone相关配置 apply plugin: "net.ltgt.errorprone" }

开启/关闭部分检查

Error-prone plugin提供了方法允许我们配置bugpattern的处理方式。

基本的做法是

1 2 3

tasks.withType(JavaCompile) { options.compilerArgs += [ '-Xep:<checkName>[:severity]' ] }

比如我们想要将ArrayToString从ERROR转成WARNING,我们可以这样做

1 2 3

tasks.withType(JavaCompile) { options.compilerArgs += [ '-Xep:ArrayToString:WARN' ] }

除此之外还有一些特殊的参数

  • -XepAllErrorsAsWarnings 将全部的Error转成WARNING
  • -XepAllDisabledChecksAsWarnings 开启全部的check,之前禁止的作为WARNING级别处理
  • -XepDisableAllChecks 关闭所有的check

其他的参数可以具体参考ErrorProneOptions.java

分条件开启error-prone插件

理论上,error-prone在编译时期进行代码分析并检查,会延长了编译时间,加之Gradle编译本来就很慢,为了不对我们日常的构建造成影响,我们可以分条件开启error-prone,即

  • 在日常开发构建,禁止应用error-prone插件,不对构建时间影响
  • 在特殊场景,比如持续集成时应用error-prone插件,用来发现问题。

具体的做法是通过想gradle传递参数来实现。简易代码如下。

1 2 3 4 5 6 7 8 9

allprojects { repositories { jcenter() } //如果接受的参数有enableErrorProne则应用插件,否则不应用 if (project.hasProperty("enableErrorProne")) { apply plugin: "net.ltgt.errorprone" } }

使用如下,则会开启应用插件

1

./gradlew assembleDebug -PenableErrorProne

注意

  • 由于是静态分析工具,即使问题代码不被执行也会检测出来。
  • 一次编译过程中,error-prone可以报出多个错误
  • Android Studio也有对应的error-prone插件,大家也可以使用。

以上就是关于error-prone的一些简单总结。Error-prone在Flipboard中已经应用很久,采用的方式为开发构建时不开启,在持续集成时开启。大家可根据自己和团队的需要选择并应用error-prone,来快速发现问题并改善代码的质量。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java架构沉思录

Java中的锁原理、锁优化、CAS、AQS

Java编程语言允许线程访问共享变量, 为了确保共享变量能被准确和一致地更新,线程应该确保通过排他锁单独获得这个变量。Java语言提供了volatile,在某些...

932
来自专栏Java架构师学习

成为顶尖程序员不得不经历的面试题

一、数据结构与算法基础 · 说一下几种常见的排序算法和分别的复杂度。 · 用Java写一个冒泡排序算法 · 描述一下链式存储结构。 · 如何遍历一棵二叉树? ·...

43211
来自专栏王磊的博客

Java核心(三)并发中的线程同步与锁

乐观锁、悲观锁、公平锁、自旋锁、偏向锁、轻量级锁、重量级锁、锁膨胀...难理解?不存的!来,话不多说,带你飙车。

1122
来自专栏Seebug漏洞平台

Spring MVC 目录穿越漏洞(CVE-2018-1271)分析

2018年04月05日,Pivotal公布了Spring MVC存在一个目录穿越漏洞(CVE-2018-1271)。Spring Framework版本5.0到...

3092
来自专栏Java帮帮-微信公众号-技术文章全总结

SpringMVC框架复习大纲【面试+提高】

2214
来自专栏猛牛哥的博客

快手(AAU)更新记录v2.9.1.23

1867
来自专栏非著名程序员

Dagger2图文完全教程

? 没有更多开场白,直接说下我对它的理解。 Dagger2 是一个Android依赖注入框架。而android开发当前非常流行的非MVP模式莫属了,Dagge...

5948
来自专栏极客日常

kubernetes源码阅读笔记:理清 kube-apiserver 的源码主线

我最近开始研究 kubernetes 源码,希望将阅读笔记记录下来,分享阅读思路和心得,更好的理解 kubernetes,这是第一篇,从 kube-apiser...

3283
来自专栏Android 研究

Android系统启动——2init进程

严格上讲,Android系统实际上是运行于Linux内核之上的一系列"服务进程",并不算一个完成意义上的"操作系统";而这一系列进程是维持Android设备正常...

1932
来自专栏菩提树下的杨过

oracle odp.net 32位/64位版本的问题

如果你的机器上安装了odp.net,且确信machine.config也有类似以下结节:(64位+.net 4.0环境下,machine.config可能会有4...

2646

扫码关注云+社区