从定义最简单Findbugs Detector做起

创建Eclipse项目

在eclipse中新建一个Java项目,使用jdk 1.7,从版本3.0开始Findbugs要求Java 7。项目名称符合Java项目名即可,这里以FB Plugin为例。

设置CLASSPATH

为了开发一个detector,我们需要对FindBugs的detector进行扩展,这里要使用到FindBugs的一些jar包。下载最新版本的FindBugs,在lib目录下找到findbugs.jar, bcel.jar,并将其添加到项目FB Plugin 的Build Path中。

编写BUG Detector

这里介绍一个FindBugs的例子(DMI_BIGDECIMAL_CONSTRUCTED_FROM_DOUBLE),用来检测BigDecimal实例使用Double进行构造。

BigDecimal a = new BigDecimal(0.1);

实际a值为:0.1000000000000000055511151231257827021181583404541015625。

具体代码如下:

package com.cqu.edu.test;

import java.math.BigDecimal;

import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.BugReporter;
import edu.umd.cs.findbugs.OpcodeStack;
import edu.umd.cs.findbugs.bcel.OpcodeStackDetector;

public class DetectorTutorial extends OpcodeStackDetector {

    private BugReporter bugReporter;

    public DetectorTutorial(BugReporter bugReporter) {
        this.bugReporter = bugReporter;
    }

    @Override
    public void sawOpcode(int seen) {
        // TODO Auto-generated method stub
        if (seen == INVOKESPECIAL && getClassConstantOperand().equals("java/math/BigDecimal")
                && getNameConstantOperand().equals("<init>") && getSigConstantOperand().equals("(D)V")) {
            OpcodeStack.Item top = stack.getStackItem(0);
            Object value = top.getConstant();
            if (value instanceof Double) {
                double arg = ((Double) value).doubleValue();
                String dblString = Double.toString(arg);
                String bigDecimalString = new BigDecimal(arg).toString();
                boolean ok = dblString.equals(bigDecimalString) || dblString.equals(bigDecimalString + ".0");

                if (!ok) {
                    boolean scary = dblString.length() <= 8 && dblString.toUpperCase().indexOf("E") == -1;
                    bugReporter.reportBug(new BugInstance(this, "TUTORIAL_BUG", scary ? NORMAL_PRIORITY : LOW_PRIORITY)
                            .addClassAndMethod(this).addString(dblString).addSourceLine(this));
                }
            }
        }
    }

}

部署和测试

FindBugs的插件是一个jar包,但至少需要包含findbugs.xml两个messages.xml文件,将这两个文件置于FB Plugin项目的根目录下。

findbugs.xml告诉告诉FindBugs你的插件的内容,及如何加载它:

<FindbugsPlugin xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="findbugsplugin.xsd"
        pluginid="com.cqu.edu.test.pluginTest"
        provider="FindBugs Test"
        website="http://findbugs.sourceforge.net">

        <Detector class="com.cqu.edu.test.DetectorTutorial" reports="TUTORIAL_BUG" />
        <BugPattern type="TUTORIAL_BUG" abbrev="TU" category="CORRECTNESS"/>

</FindbugsPlugin>

messages.xml包括了该插件的英文描述,和其报告的bug pattern:

<?xml version="1.0" encoding="UTF-8"?>
<MessageCollection xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="messagecollection.xsd">

        <Plugin>
                <ShortDescription>FindBugs Plugin Tutorial Plugin</ShortDescription>
                <Details>Provides detectors as part of the FindBugs detector plugin tutorial.</Details>
        </Plugin>

        <Detector class="com.cqu.edu.test.DetectorTutorial">
                <Details>
                        Finds instances of BigDecimals being created
                        with doubles.
                </Details>

        </Detector>

        <BugPattern type="TUTORIAL_BUG">
                <ShortDescription>BigDecimal created from double</ShortDescription>
                <LongDescription>BigDecimal created from double in {1}</LongDescription>
                <Details>
<![CDATA[
<p>Due to the way double-precision floating point values are represented in Java, creating a new BigDecimal from a double is unreliable and may produce surprising results.</p>
]]>
                </Details>
        </BugPattern>

        <BugCode abbrev="TU">Tutorial</BugCode>
</MessageCollection>

将FB Plugin项目build为jar包,勾选图中文件:

将打包的jar文件放到FindBugs的plugin目录下,在运行FindBugs时即可被调用。

原文链接:https://code.google.com/p/findbugs/wiki/DetectorPluginTutorial

时间: 2024-10-15 13:53:39

从定义最简单Findbugs Detector做起的相关文章

mysql 自动定义序号:用来做"定单号"

自动定义序号:用来做"定单号" 总会有这样的需求,只是可能你没有遇到而已.我举个例子:若订单号的生成格式为"日期+序号" (先不管需求是不是很傻逼),就像这样:2015052200001234,这个该如何处理呢? 若是有序列号,就比较好解决了.从00000001开始,到99999999,然后重置为一下序列,就OK啦. -- 定义序列表 DROP TABLE IF EXISTS sequence; CREATE TABLE sequence ( name VARCHA

类定义(课下选做)

类定义(课下选做) 要求 Book类包含书名,作者,出版社和出版日期 数据都要定义getter和setter 至少三个构造方法,接收并初始化这些数据 覆盖toString方法,返回良好的含有多行的书的描述信息 覆盖equals方法,书名.作者.出版社和出版日期完全相同说明两本书相同. 创建一个测试类BookShelf 思路 根据要求最好分为两个类,即Book和BookShelf 在Book类中定义四个getter,返回书名.作者.出版社和出版日期 在BookShelf类中定义四个setter,赋

C宏定义的简单总结 (转)

1,防止一个头文件被重复包含  #ifndef BODYDEF_H #define BODYDEF_H   //头文件内容 #endif 2,得到指定地址上的一个字节或字 #define  MEM_B( x )  ( *( (byte *) (x) ) ) #define  MEM_W( x )  ( *( (word *) (x) ) ) 3,得到一个field在结构体(struct)中的偏移量 #define FPOS( type, field ) ( (dword) &(( type *)

Oracle数据库零散知识06 -- Package的定义与简单触发器

CREATE OR REPLACE PACKAGE pak_02 IS--包头 --这里可定义公共参数 FUNCTION fun_01 RETURN NUMBER; PROCEDURE pro_01 ; END; CREATE OR REPLACE PACKAGE BODY pak_02 IS--包体 --这里可定义私有变量 FUNCTION fun_01 RETURN NUMBER IS BEGIN RETURN 666; END; PROCEDURE pro_01 IS BEGIN dbms

NGUI之Slider,最简单的方法做进度条。

既然标题是最简单的,那么很多东西就不需要我们自己做了,使用的是NGUI的示例,只针对初学者,接下来让我们来做一个最简单游戏设置里的声音控制. 1.导入NGUI: 2.找到NGUI的Menu示例Demo,文件夹为NGUI\Examples\Scenes 打开Example 3 - Menu场景 3.在Hierarchy视图中找到Option - Voice游戏对象[灰色的active没有启用的对象] 4.复制改游戏对象,并在你的项目的Hierarchy视图中粘贴到合适的位置,并将active启用(

从简单的事做起: Instagram背后的工程学

原文链接:DO THE SIMPLE THING FIRST: THE ENGINEERING BEHIND INSTAGRAM 译者:李伟 规模小的时候,克服困难很容易.规模扩大后,就困难了 当Instagram于2010年10月在iPhone应用商店上架的时候,这时的开发团队只有2个人:创始人Kevin Systrom和Mike Krieger.他们都没有什么传统的软件工程背景(Systrom在斯坦福大学专业是管理科学,Krieger学的是符号系统(symbolic systems).)当这

CF简单题选做

And Reachability 给定一个长度为 \(n\) 的序列 \(a\) ,定义 \((x,y)\) "可到达" 为:可以选出若干个位置 \(p_1...p_k\) ,使得 \(\forall x\le p_i \le y\) \(\forall a_{p_i}\&a_{p_{i+1}}\not=0\) , \(q\) 次询问 \((x,y)\) 是不是 "可到达" 的 \(n,q,a_i\le 3\times 10^5\) tags : dp ,

git的简单命令--仅做个人实验用,如用在公司开发上后果自负

本文是引自廖雪峰老师git教程网--http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000 git???clone   &    push 环境是码云不是GitHub(虽然差不多),仅是在Windows上的操作 下面这些命令的执行前提是你已经正确安装了git(你也可以在开始菜单里找到"Git"->"Git Bash"),安装完最后执行了 $gi

Hibernate SQLQuery简单实用,做链接查询

工单里面可能有0个告警,一个或多个告警,当工单中没有告警的时候也需要将工单显示出来,所以就需要使用工单和告警的做链接查询,下面是具体实例 表: CREATE TABLE `alarm` ( `id` bigint(20) NOT NULL DEFAULT '0', `title` varchar(20) DEFAULT NULL, `level` int(11) DEFAULT NULL, `customer_id` bigint(20) DEFAULT NULL, `work_sheet_id