使用FindBugs分析并发代码

Java 9并发编程指南 目录

静态代码分析工具是分析应用程序的源代码,同时查找潜在的错误的一组工具。这些工具如Checkstyle、PMD或FindBugs,具有一组预定义的良好实践规则,并解析源代码,查找违反这些规则的地方。使用这些工具的目的是在正式上线执行之前的早期阶段,发现错误或者导致性能底下的位置。编程语言通常提供类似工具,Java也不例外,FindBugs是帮助分析Java代码的一个工具,它是一个开源工具,包含了一系列分析java并发代码的规则。

本节讲学习如何使用此工具分析Java并发应用。

准备工作

在开始之前,从项目网站下载FindBugs(http://findbugs.sourceforge.net/),可以下载独立应用或者Eclipse的插件。本节使用独立版本。

编写本书时,FindBugs(3.0.1)的实际版本不支持Java 9,可以下载支持Java 9 的3.1.0预览版,网址是https://github.com/findbugsproject/findbugs/releases/tag/3.1.0_preview1

实现过程

通过如下步骤实现范例:

  1. 创建名为Task的类,继承Runnable接口:

    public class Task implements Runnable{
    
  2. 声明名为lock的私有ReentrantLock属性:

    	private ReentrantLock lock;
    
  3. 实现类构造函数:

    	public Task(ReentrantLock lock) {
    		this.lock=lock;
    	}
    
  4. 实现run()方法,获得锁控制权,设置线程休眠2秒钟,然后释放锁:

    	@Override
    	public void run() {
    		lock.lock();
    		try {
    			TimeUnit.SECONDS.sleep(1);
    			lock.unlock();
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    	}
    }
    
  5. 实现本范例主类,创建名为Main的类,包含main()方法:

    public class Main {
    	public static void main(String[] args) {
    
  6. 声明和创建名为lock的ReentrantLock对象:

    		ReentrantLock lock=new ReentrantLock();
    
  7. 创建10个Task对象和10个执行这些任务的线程,通过调用run()方法启动线程:

    		for (int i=0; i<10; i++) {
    			Task task=new Task(lock);
    			Thread thread=new Thread(task);
    			thread.run();
    		}
    	}
    }
    
  8. 导出工程为recipe7.jar文件,使用IDE的菜单选项或者javac、.jar命令来编译和压缩本范例。

  9. 在Windows系统中运行findbugs.bat命令或者Linux中的findbugs.sh命令,启动FindBugs独立应用。

  10. 通过点击菜单栏中的File按钮下的New Project**选项,创建新工程:

    pics/09_02.jpg

  11. FindBugs软件打开配置工程的窗口,在Project name区域输入Recipe07。在Classpath for analysis field (jar, ear, war, zip, or directory) 里添加工程.jar文件。在Source directories field (optional; classes used when browsing found bugs) 里添加范例的源代码。如下图所示:

    pics/09_03.jpg

  12. 点击Analyze按钮创建新工程,分析代码。

  13. FindBugs软件展示代码分析结果,在本范例中发现了两处问题。

  14. 单击其中一个问题,将在右侧面板中看到此问题的源代码,并在屏幕底部面板中显示问题描述。

工作原理

下图显示通过FindBugs分析的结果:

pics/09_04.jpg

在应用中检测出如下两个潜在问题:

  • 其中一个问题是在Task类的run()方法中,如果抛出InterruptedExeption异常,任务无法释放锁,因为任务不执行unlock()方法。这在应用中可能导致死锁。
  • 另一个问题在Main类的main()方法中,因为直接调用了线程的run()方法,而不是开始线程执行的start()方法。

如果双击其中一个问题,将会看到问题详细信息。由于已经在项目配置中引用源代码,还能看到检测到错误的源代码。如下图所示:

pics/09_05.jpg

扩展学习

注意FindBugs只能检测一些有问题的情况(是否与并发代码相关)。例如,如果在Task类的run()方法中删除unlock()调用,然后重复此分析。FindBugs不会警告得到任务中的锁,但也永远无法释放它。

使用静态代码分析工具有助于提高代码质量,但不要期望它能够检测所有错误。

更多关注

  • 本章“配置NetBeans调试并发代码”小节

猜你喜欢

转载自blog.csdn.net/nicolastsuei/article/details/84648462