编写新的findbugs检测器
Why?
你也许找到代码里的错误典型
How?
检查字节码
有很多途径去实现findbugs的检测器
通常,简单技巧就够了(如:顺序扫描)
基本途径
1.从一个Bug开始(重要!)
2.编写可以查找到类似问题的最简单的检测器
3.评估:它是否能够找到足够相关的问题而没有太多的误检
4.提炼:提升分析和FP suppression heuristics
5.重复步骤3-4直到你认为可以接受或者放弃这个想法
字节码框架
所有findbugs的检测器的工作都是基于分析字节码。支撑的框架:
BCEL(http://jakarta.apache.org/bcel);DOM-like API
ASM(http://asm.objectweb.org/);SAX-like API
当前,许多配套的findbugs基础架构是基于BCEL的。
基于ASM分析的检测器是实验性的。
检测器的分类
大多数findbugs的检测器使用下面的一类实现技巧:
1.检查class/method/field结构
2.微模型化:简单的字节码模型
3.基于栈的模型
4.数据流分析
5.过程间(函数间 Interprocedural)分析
每一种技术都现成的基类和支撑的基础架构。
检查class/method/field结构
一些检测器并不要求代码分析.如:
查找重写了equals方法却没有重写hashCode方法的类
查找命名错误的方法(如:hashcode()代替hashCode())
微模型化:简单的字节码模型
如:无条件的等待
源码:
synchronized(lock){
lock.wait();
...
}
对应的字节码:
ALOAD 0
GETFIELD A.lock
DUP
ASTORE 1
MONITORENTER
ALOAD 0
GETFIELD A.lock
INVOKEVIRTUAL
Object.wait()V
检测器状态(Detector states):
基于栈的模型
微模型那些在操作栈上的值是有标志性的:
如:之前看到的,查找常量字符串类型的值是monitorenter
典型的实现策略:
1.调查操作栈上的值
2.当看到可疑的指令序列或堆栈值时发出警告
数据流分析
1.使用过程间的数据流分析来推断方法间可能的实情(fact)
你可能需要温习dragon book(查了下,可能是<Compilers:Principles,Techniques,and Tools>)
2.范例:
查找空指针
查找字段访问没有被一个锁一致地保护。
过程间的分析
概括方法行为,并在每一个调用位置使用这个总结。如:
1.无条件间接引用的方法参数
2.返回值总是非空的值
3.总是抛异常的方法
更多信息
http://code.google.com/p/findbugs-tutorials
1. PLDI教程幻灯片,使用findbugs做研究
关于编写findbugs的检测器的深入讨论
2. 有两个检测器的插件范例源码