java自定义findbugs规则_静态代码扫描 (三)——FindBugs 自定义规则入门
準(zhǔn)備工作
由于 FindBugs 是分析編譯后的 class 文件,也就是字節(jié)碼文件。我們需要了解 FindBugs 底層的處理機(jī)制。根據(jù)FindBugs 官網(wǎng)文檔描述,FindBugs 使用了BCEL來(lái)分析 Java 字節(jié)碼文件。從 1.1 版本開(kāi)始,FindBugs 也支持使用ASM字節(jié)碼框架來(lái)編寫(xiě) bug 探測(cè)器。
我們需要下載 FindBugs 源碼版用來(lái)新增自定義探測(cè)器:findbugs-3.0.1-source.zip
也需要下載 FindBugs 標(biāo)準(zhǔn)版:findbugs-3.0.1.zip,將 findbugs.jar 替換為我們的自定義版本后,運(yùn)行查看結(jié)果。
自定義規(guī)則
自定義規(guī)則思路:
明確要定義的規(guī)則。
分析樣例代碼的字節(jié)碼內(nèi)容。
編寫(xiě)探測(cè)器。
將規(guī)則加入規(guī)則文件中。
1. 明確要定義的規(guī)則
我將以一個(gè)非常簡(jiǎn)單的規(guī)則舉例:代碼中避免使用有類似 System.out 的輸出語(yǔ)句。
package main;
public class TestFindBugs {
public static void main(String[] args) {
System.out.println("123"); //bug
System.err.println("123"); //bug
}
}
2. 分析樣例代碼的字節(jié)碼內(nèi)容
為了更方便的分析樣例代碼的字節(jié)碼內(nèi)容,這里推薦一個(gè) Eclipse 上用來(lái)查看 java 文件字節(jié)碼內(nèi)容的插件:
Bytecode Outline
官網(wǎng)地址:http://andrei.gmxhome.de/bytecode/index.html
在安裝完成后,通過(guò) Bytecode 工具編譯后的字節(jié)碼文件內(nèi)容:
// class version 51.0 (51)
// access flags 0x21
public class main/TestFindBugs {
// compiled from: TestFindBugs.java
// access flags 0x1
public ()V
L0
LINENUMBER 3 L0
ALOAD 0
INVOKESPECIAL java/lang/Object. ()V
RETURN
L1
LOCALVARIABLE this Lmain/TestFindBugs; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
// access flags 0x9
public static main([Ljava/lang/String;)V
L0
LINENUMBER 5 L0
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
LDC "123"
INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
L1
LINENUMBER 6 L1
GETSTATIC java/lang/System.err : Ljava/io/PrintStream;
LDC "123"
INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
L2
LINENUMBER 7 L2
RETURN
L3
LOCALVARIABLE args [Ljava/lang/String; L0 L3 0
MAXSTACK = 2
MAXLOCALS = 1
}
通過(guò)查看字節(jié)碼文件分析,我們找到了一些關(guān)鍵語(yǔ)句:
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
GETSTATIC java/lang/System.err : Ljava/io/PrintStream;
3. 編寫(xiě)探測(cè)器
我們通過(guò)剛才找到的關(guān)鍵語(yǔ)句,結(jié)合我們的邏輯,進(jìn)行探測(cè)器編寫(xiě):
package edu.umd.cs.findbugs.detect;
import org.apache.bcel.classfile.Code;
import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.BugReporter;
import edu.umd.cs.findbugs.bcel.OpcodeStackDetector;
/**
* @author yuanwei
* @category 代碼中避免使用有類似System.out的輸出語(yǔ)句
*/
public class ForbiddenSystemClass extends OpcodeStackDetector {
BugReporter bugReporter;
public ForbiddenSystemClass(BugReporter bugReporter) {
this.bugReporter = bugReporter;
}
/**
* visit方法,在每次進(jìn)入字節(jié)碼方法的時(shí)候調(diào)用 在每次進(jìn)入新方法的時(shí)候清空標(biāo)志位
*/
@Override
public void visit(Code obj) {
super.visit(obj);
}
/**
* 每掃描一條字節(jié)碼就會(huì)進(jìn)入sawOpcode方法
*
* @param seen
* 字節(jié)碼的枚舉值
*/
@Override
public void sawOpcode(int seen) {
if (seen == GETSTATIC) {
if (getClassConstantOperand().equals("java/lang/System")) {
if(getNameConstantOperand().equals("out") || getNameConstantOperand()
.equals("err")){
BugInstance bug = new BugInstance(this, "CJ_SYSTEMCLASS",
NORMAL_PRIORITY).addClassAndMethod(this).addSourceLine(
this, getPC());
bugReporter.reportBug(bug);
}
}
}
}
}
4. 將規(guī)則加入規(guī)則文件中
我們剛才在編寫(xiě)探測(cè)器的時(shí)候,已經(jīng)給定了規(guī)則的名稱CJ_SYSTEMCLASS。現(xiàn)在我們需要將這個(gè)規(guī)則添加在配置文件中。
配置 findbugs.xml:
配置 message.xml:
Default FindBugs plugin
This plugin contains all of the standard FindBugs detectors.
]]>
代碼不能出現(xiàn)System.out
請(qǐng)使用log日志形式打印
]]>
代碼不能出現(xiàn)System.out
{1}代碼不能出現(xiàn)System.out,請(qǐng)使用log形式輸出
不能使用System.out和System.err,請(qǐng)使用log
]]>
影響性能的輸出System.out
規(guī)則添加完成后,重新打包 findbugs.jar:
mvn clean install -Dmaven.test.skip=true
打包成功后,在可運(yùn)行版本的 findbugs 中替換原來(lái)的/lib/findbugs.jar
執(zhí)行 findbugs 命令,掃描樣例文件的 class 文件,查看運(yùn)行結(jié)果:
在掃描結(jié)果中,可以看出確實(shí)掃描到了我們?cè)O(shè)定的問(wèn)題語(yǔ)句。
使用 FindBugs 自定義規(guī)則成功!
參考文獻(xiàn)
360Qtest 團(tuán)隊(duì)公眾號(hào)
關(guān)注公眾號(hào),第一時(shí)間收到我們推送的新文章~
超強(qiáng)干貨來(lái)襲 云風(fēng)專訪:近40年碼齡,通宵達(dá)旦的技術(shù)人生總結(jié)
以上是生活随笔為你收集整理的java自定义findbugs规则_静态代码扫描 (三)——FindBugs 自定义规则入门的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: java mapreduce 标准差_M
- 下一篇: java new的是构造函数_Java构