在Gradle中使用FindBugs

代码检查之FindBugs

题图:from Google

什么是FindBugs?

作为程序猴子,哪个没有被虫子困扰过,每次debug都是一次痛苦的过程。如果有一个工具可以帮我们找到那些跟我捉迷藏的bug,这个世界岂不是会变得很美好?
OK,FindBugs来了,它就是那个让世界变得更加美好的工具。
FindBugs是一个java静态分析工具,它检查类或者JAR文件,有了FindBugs,无需运行运行程序即可找到潜在的Bug。当然,它无法找到所有bug(完美的工具总是存在梦里),但目前的FindBugs已经足够强大,可以找出绝大多数潜在问题了。

配置FindBugs

一个拥有如此强大功能的工具,它的配置却是十分简单。FindBugs几乎是开箱即用,无需配置即可进行代码审计。
不过,它也支持自定义配置,可以自定义需要检查的类或文件,也可以自定义不进行检查的类或文件。
自定义的核心就是Filter File(xml文件)的配置。我们既可以指定该文件为需要检查的也可以指定其为忽略检查的。
这里只介绍Filter File的配置,其他内容见附录FindBugs文档链接。
首先来看一个示例配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<FindBugsFilter>
<Match>
<Class name="com.foobar.ClassNotToBeAnalyzed" />
</Match>
<Match>
<Class name="com.foobar.ClassWithSomeBugsMatched" />
<Bug code="DE,UrF,SIC" />
</Match>
<!-- Match all XYZ violations. -->
<Match>
<Bug code="XYZ" />
</Match>
<!-- Match all doublecheck violations in these methods of "AnotherClass". -->
<Match>
<Class name="com.foobar.AnotherClass" />
<Or>
<Method name="nonOverloadedMethod" />
<Method name="frob" params="int,java.lang.String" returns="void" />
<Method name="blat" params="" returns="boolean" />
</Or>
<Bug code="DC" />
</Match>
<!-- A method with a dead local store false positive (medium priority). -->
<Match>
<Class name="com.foobar.MyClass" />
<Method name="someMethod" />
<Bug pattern="DLS_DEAD_LOCAL_STORE" />
<Priority value="2" />
</Match>
<!-- All bugs in test classes, except for JUnit-specific bugs -->
<Match>
<Class name="~.*\.*Test" />
<Not>
<Bug code="IJU" />
</Not>
</Match>
</FindBugsFilter>

话不多说,直接看文件。除了根级FindBugsFilter元素外,都是使用Match元素进行匹配的设置,而Match元素中仅有几种属性而已,因此,只要了解这些属性之后,即可随意配置自己需要的Filter File了。(别忘了,FindBugs开箱即用,即使没有Filter File也是可以直接审计的 : ) )

匹配类型如下所示:

PS:
如果在name等支持regex的属性中使用“~”开头,会被解析为javaRegexPattern
考虑到通配符是匹配所有元素,因此.\*应该加在首部,以及and/or的尾部来保证substring的匹配

Gradle中使用FindBugs插件

Gradle本身就已经支持了FindBugs插件,因此我们只需要很简单的几步配置即可gradle findbugsMain进行代码审计了。
首先,官方示例配置如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
apply plugin: "java"
apply plugin: "findbugs"
findbugs {
toolVersion = "2.0.1"
sourceSets = [sourceSets.main]
ignoreFailures = true
reportsDir = file("$project.buildDir/findbugsReports")
effort = "max"
reportLevel = "high"
visitors = ["FindSqlInjection", "SwitchFallthrough"]
omitVisitors = ["FindNonShortCircuit"]
includeFilter = file("$rootProject.projectDir/config/findbugs/includeFilter.xml")
excludeFilter = file("$rootProject.projectDir/config/findbugs/excludeFilter.xml")
excludeBugsFilter = file("$rootProject.projectDir/config/findbugs/excludeBugsFilter.xml")
}

这里说下常用配置属性的意义:

附录

想必有了上述两者的配置说明,大家已经可以自己配置想要的Findbugs并使用了。
如果觉得不够,例如想尝试下FindBugs的注解等特性,大家可以参照文档深入研究。
下面附上几个文档的链接:

Bug类型:FindBugs Bug Descriptions: http://findbugs.sourceforge.net/bugDescriptions.html)
FindBugs Manul: http://findbugs.sourceforge.net/manual/
Gradle Findbugs插件用户指南:https://docs.gradle.org/current/userguide/findbugs_plugin.html