Introduction to FindBugs – FindBugs简介

最后修改: 2016年 11月 5日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

FindBugs is an open source tool used to perform static analysis on Java code.

FindBugs是一个开源工具,用于对Java代码进行静态分析

In this article, we’re going to have a look at setting up FindBugs on a Java project and integrating it into the IDE and the Maven build.

在本文中,我们将看看如何在一个Java项目上设置FindBugs,并将其集成到IDE和Maven构建中。

2. FindBugs Maven Plugin

2.FindBugs Maven Plugin

2.1. Maven Configuration

2.1.Maven配置

In order to start generating static analysis reports, we first need to add the FindBugs plugin in our pom.xml:

为了开始生成静态分析报告,我们首先需要在我们的pom.xml中添加FindBugs插件。

<reporting>
    <plugins>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>findbugs-maven-plugin</artifactId>
            <version>3.0.4</version>
        </plugin>
    </plugins>
</reporting>

You can check out the latest version of the plugin on Maven Central.

您可以在Maven中心查看最新版本的插件

2.2. Report Generation

2.2.报告生成

Now that we have the Maven plugin properly configured, let’s generate the project documentation using the mvn site command.

现在我们正确配置了Maven插件,让我们用mvn site命令生成项目文档。

The report will be generated in the folder target/site in the project directory under the name findbugs.html.

报告将在项目目录的target/site文件夹中生成,名称为findbugs.html

You can also run the mvn findbugs:gui command to launch the GUI interface to browse the generated reports for the current project.

你也可以运行mvn findbugs:gui命令来启动GUI界面,浏览当前项目的生成的报告。

The FindBugs plugin can also be configured to fail under some circumstances – by adding the execution goal check to our configuration:

FindBugs插件也可以被配置为在某些情况下失败–通过在我们的配置中加入执行目标check

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>findbugs-maven-plugin</artifactId>
    <version>3.0.4</version>
    <configuration>
        <effort>Max</effort>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>check</goal>
            </goals>
        </execution>
    </executions>
</plugin>

The effort – when maxed out, performs a more complete and precise analysis, revealing more bugs in the code, though, it consumes more resources and takes more time to complete.

effort–当达到最大值时,执行更完整和精确的分析,揭示代码中更多的bug,不过,它消耗更多的资源,需要更多的时间来完成。

You can now run the command mvn verify, to check if the build will succeed or not – depending on the defects detected while running the analysis.

现在你可以运行mvn verify命令,检查构建是否会成功–取决于运行分析时检测到的缺陷。

You can also enhance the report generation process and take more control over the analysis, by adding some basic configuration to the plugin declaration:

你还可以通过在插件声明中添加一些基本配置,来加强报告生成过程,并对分析进行更多控制。

<configuration>
    <onlyAnalyze>org.baeldung.web.controller.*</onlyAnalyze>
    <omitVisitors>FindNullDeref</omitVisitors>
    <visitors>FindReturnRef</visitors>
</configuration>

The onlyAnalyze option declares a comma separated values of classes/packages eligible for analysis.

onlyAnalyze选项声明了一个逗号分隔的符合分析条件的类/包的值。

The visitors/omitVisitors options are also comma separated values, they are used to specify which detectors should/shouldn’t be run during the analysis – Note that visitors and omitVisitors cannot be used at the same time.

visitors/omitVisitors选项也是逗号分隔的值,它们被用来指定在分析过程中应该/不应该运行哪些检测器 – 注意,visitorsomitVisitors不能同时使用

A detector is specified by its class name, without any package qualification. Find the details of all detectors class names available by following this link.

探测器是由其类名指定的,没有任何包的限定。按照这个链接,可以找到所有检测器类名的细节。

3. FindBugs Eclipse Plugin

3.FindBugs Eclipse插件

3.1. Installation

3.1.安装

The IDE installation of the FindBugs Plugin is pretty straightforward – you just need to use the software update feature in Eclipse, with the following update site: http://findbugs.cs.umd.edu/eclipse.

FindBugs插件的IDE安装非常简单 – 你只需要使用Eclipse,中的软件更新功能,更新网站如下。http://findbugs.cs.umd.edu/eclipse.

To make sure that FindBugs is properly installed in your Eclipse environment, then, look for the option labeled FindBugs under Windows -> Preferences -> Java.

要确保FindBugs已经正确地安装在你的Eclipse环境中,那么就在Windows -> Preferences -> Java下寻找标有FindBugs的选项。

3.2. Reports Browsing

3.2.报告浏览

In order to launch a static analysis on a project using the FindBugs Eclipse plugin, you need to right-click the project in the package explorer, then, click on the option labeled find bugs.

为了使用FindBugs Eclipse插件对一个项目进行静态分析,你需要在包资源管理器中右键单击该项目,然后,单击标有查找错误的选项。

After launch, Eclipse shows the results under the Bug Explorer window as shown in the screenshot below:

启动后,Eclipse在Bug Explorer窗口下显示结果,如下图所示。

bug explorer
As of version 2, FindBugs started ranking bugs with a scale from 1 to 20 to measure the severity of defects:

bug explorer
从第2版开始,FindBugs开始用1到20的等级来衡量缺陷的严重程度。

  • Scariest: ranked between 1 & 4.
  • Scary: ranked between 5 & 9.
  • Troubling: ranked between 10 & 14.
  • Of concern: ranked between 15 & 20.

While the bug rank describes severity, the confidence factor reflects the likelihood of these bugs to be flagged as real ones. The confidence was originally called priority, but it was renamed in the new version.

虽然bug等级描述了严重性,但置信度因素反映了这些bug被标记为真实bug的可能性。置信度最初被称为优先级,但在新版本中被重新命名。

Of course, some defects can be open to interpretation, and they can even exist without causing any harm to the desired behavior of a software. That’s why, in a real-world situation, we need to properly configure static analysis tools by choosing a limited set of defects to activate in a specific project.

当然,有些缺陷是可以解释的,它们甚至可以存在而不对软件的预期行为造成任何伤害。这就是为什么在现实世界中,我们需要正确地配置静态分析工具,在特定的项目中选择一组有限的缺陷来激活。

3.3. Eclipse Configuration

3.3.Eclipse配置

FindBugs plugin makes it easy to customize the bugs analysis strategy, by offering various ways to filter warning and limit the strictness of the results. You can check the configuration interface by going to Window -> Preferences -> Java -> FindBugs:

FindBugs插件通过提供各种方式来过滤警告和限制结果的严格性,从而使定制错误分析策略变得容易。你可以通过进入Window -> Preferences -> Java -> FindBugs来检查配置界面。

fb preferences 1

 

You can freely uncheck unwanted categories, raise the minimum rank to report, specify the minimum confidence to report, and customize markers for bugs ranks – Warning, Info, or Error.

你可以自由地取消不需要的类别,提高报告的最低等级,指定报告的最低可信度,并为错误等级定制标记–警告、信息或错误。

FindBugs divide defects in many categories:

FindBugs将缺陷分为许多类别。

  • Correctness – gathers general bugs, e.g. infinite loops, inappropriate use of equals(), etc
  • Bad practice, e.g. exceptions handling, opened streams, Strings comparison, etc
  • Performance, e.g. idle objects
  • Multithreaded correctness – gathers synchronization inconsistencies and various problems in a multi-threaded environment
  • Internationalization – gathers problems related to encoding and application’s internationalization
  • Malicious code vulnerability – gathers vulnerabilities in code, e.g. code snippets that can be exploited by potential attackers
  • Security – gathers security holes related to specific protocols or SQL injections
  • Dodgy – gathers code smells, e.g. useless comparisons, null checks, unused variables, etc

Under the Detector configuration tab, you can check the rules you’re supposed to respect in your project:

检测器配置标签下,你可以检查你的项目中应该遵守的规则。

fb preferences_detector 1

The speed attribute reflects how costly the analysis will be. The fastest the detector, the smallest the resources consumed to perform it.

速度属性反映了分析的成本有多高。检测器的速度越快,执行它所消耗的资源就越少。

You can find the exhaustive list of bugs recognized by FindBugs at the official documentation page.

你可以在官方文档页找到FindBugs识别的详尽的错误列表。

Under the Filter files panel, you can create custom file filters, in order to include/exclude parts of the code-base. This feature is useful – for example – when you want to prevent “unmanaged” or “trash” code, defects to pop up in the reports, or may exclude all classes from the test package for instance.

过滤文件面板下,您可以创建自定义文件过滤器,以便包括/排除代码库的部分内容。这个功能很有用,例如,当你想防止 “未管理 “或 “垃圾 “代码、缺陷在报告中出现时,或者可以排除测试包中的所有类。

4. FindBugs IntelliJ IDEA Plugin

4.FindBugs IntelliJ IDEA插件

4.1. Installation

4.1.安装

If you are an IntelliJ IDEA fan, and you want to start inspecting Java code using FindBugs, you can simply grab the plugin installation package from the official JetBrains site, and extract it to the folder %INSTALLATION_DIRECTORY%/plugins. Restart your IDE and you’re good to go.

如果您是 IntelliJ IDEA 的粉丝,并希望开始使用 FindBugs 检查 Java 代码,您可以简单地从JetBrains 官方网站上获取插件安装包,并将其解压到 %INSTALLATION_DIRECTORY%/plugins 文件夹中。重新启动你的IDE,你就可以了。

Alternatively, you can navigate to Settings -> Plugins and search all repositories for FindBugs plugin.

或者,你可以导航到 “设置”->”插件”,在所有软件库中搜索FindBugs插件。

By the time of writing this article, the version 1.0.1 of the IntelliJ IDEA plugin is just out,

在写这篇文章的时候,1.0.1版本的IntelliJ IDEA插件刚刚出来。

To make sure that the FindBugs plugin is properly installed, check for the option labeled “Analyze project code” under Analyze -> FindBugs.

要确保FindBugs插件已正确安装,请检查在Analyze -> FindBugs下标有 “分析项目代码 “的选项。

4.2. Reports Browsing

4.2.报告浏览

In order to launch static analysis in IDEA, click on “Analyze project code”, under Analyze -> FindBugs, then look for the FindBugs-IDEA panel to inspect the results:

为了在IDEA中启动静态分析,点击 “分析项目代码”,在Analyze -> FindBugs下,然后寻找FindBugs-IDEA面板来检查结果。

Spring rest analysis 1

You can use the second column of commands on the left side of the screenshot, to group defects using different factors:

你可以使用截图左侧的第二列命令,用不同的因素对缺陷进行分组。

  1. Group by a bug category.
  2. Group by a class.
  3. Group by a package.
  4. Group by a bug rank.

It is also possible to export the reports in XML/HTML format, by clicking the “export” button in the fourth column of commands.

也可以通过点击第四列命令中的 “导出 “按钮,将报告以XML/HTML格式导出。

4.3. Configuration

4.3.配置

The FindBugs plugin preferences pages inside IDEA is pretty self-explanatory:

IDEA内部的FindBugs插件偏好页面是不言自明的。

IntelliJ Preferences 1

This settings window is quite similar to the one we’ve seen in Eclipse, thus you can perform all kinds of configuration in an analogous fashion, starting from analysis effort level, bugs ranking, confidence, classes filtering, etc.

这个设置窗口与我们在Eclipse中看到的非常相似,因此你可以以类似的方式进行各种配置,从分析努力程度、错误排名、置信度、类别过滤等开始。

The preferences panel can be accessed inside IDEA, by clicking the “Plugin preferences” icon under the FindBugs-IDEA panel.

通过点击FindBugs-IDEA面板下的 “插件偏好 “图标,可以在IDEA内部访问偏好面板。

5. Report Analysis for the Spring-Rest Project

5.春晖计划的报告分析

In this section we’re going to shed some light on a static analysis done on the spring-rest project available on Github as an example:

在本节中,我们将以Github上的spring-rest项目为例,对其进行静态分析。

Spring rest analysis 2

Most of the defects are minor — Of Concern, but let’s see what we can do to fix some of them.

大多数缺陷是轻微的–值得关注,但让我们看看我们能做些什么来修复其中的一些缺陷。

Method ignores exceptional return value:

方法忽略了特殊的返回值:

File fileServer = new File(fileName);
fileServer.createNewFile();

As you can probably guess, FindBugs is complaining about the fact that we’re throwing away the return value of the createNewFile() method. A possible fix would be to store the returned value in a newly declared variable, then, log something meaningful using the DEBUG log level — e.g. “The named file does not exist and was successfully created” if the returned value is true.

正如你可能猜到的,FindBugs正在抱怨我们丢弃了createNewFile()方法的返回值。一个可能的解决方法是将返回值存储在一个新声明的变量中,然后,使用DEBUG日志级别记录一些有意义的东西–例如,如果返回值为真,则记录”命名的文件不存在,已成功创建“。

The method may fail to close stream on exception: this particular defect illustrates a typical use case for exception handling that suggests to always close streams in a finally block:

该方法可能无法在异常时关闭流:这个特殊的缺陷说明了异常处理的一个典型用例,即建议始终在finally块中关闭流

try {
    DateFormat dateFormat 
      = new SimpleDateFormat("yyyy_MM_dd_HH.mm.ss");
    String fileName = dateFormat.format(new Date());
    File fileServer = new File(fileName);
    fileServer.createNewFile();
    byte[] bytes = file.getBytes();
    BufferedOutputStream stream 
      = new BufferedOutputStream(new FileOutputStream(fileServer));
    stream.write(bytes);
    stream.close();
    return "You successfully uploaded " + username;
} catch (Exception e) {
    return "You failed to upload " + e.getMessage();
}

When an exception is thrown before the stream.close() instruction, the stream is never closed, that’s why it’s always preferable to make use of the finally{} block to close streams opened during a try/catch routine.

当异常在stream.close()指令之前被抛出时,流永远不会被关闭,这就是为什么最好利用finally{}块来关闭在try/catch例程中打开的流。

An Exception is caught when Exception is not thrown: As you may already know, catching Exception is a bad coding practice, FindBugs thinks that you must catch a most specific exception, so you can handle it properly. So basically manipulating streams in a Java class, catching IOException would be more appropriate than catching a more generic Exception.

Exception没有被抛出时,Exception被捕获。你可能已经知道,捕捉Exception是一种不好的编码做法,FindBugs认为你必须捕捉一个最具体的异常,这样你才能正确处理它。因此,基本上在Java类中操作流,捕捉IOException会比捕捉一个更通用的Exception更合适。

Field not initialized in the constructor but dereferenced without null check: it always a good idea to initialize fields inside constructors, otherwise, we should live with the possibility that the code will raise an NPE. Thus, it is recommended to perform null checks whenever we’re not sure if the variable is properly initialized or not.

在构造函数中没有初始化字段,但在没有进行空值检查的情况下取消引用:在构造函数中初始化字段总是一个好主意,否则,我们应该忍受代码会引发NPE的可能性。因此,当我们不确定变量是否被正确初始化时,建议执行空值检查。

6. Conclusion

6.结论

In this article, we’ve covered the basic key points to use and customize FindBugs in a Java project.

在这篇文章中,我们已经介绍了在Java项目中使用和定制FindBugs的基本要点。

As you can see, FindBugs is a powerful, yet simple static analysis tool, it helps to detect potential quality holes in your system – if tuned and used correctly.

正如你所看到的,FindBugs是一个强大而简单的静态分析工具,它有助于检测你系统中潜在的质量漏洞–如果调整和使用正确的话。

Finally, it is worth mentioning that FindBugs can also be run as part of a separate continuous automatic code review tool like Sputnik, which can be very helpful to give the reports a lot more visibility.

最后,值得一提的是,FindBugs也可以作为单独的持续自动代码审查工具的一部分来运行,如Sputnik,这对于让报告有更多的可见性非常有帮助。

The sample code we used for static analysis is available over on Github.

我们用于静态分析的示例代码可在Github上获得over