java自定义findbugs规则_静态代码扫描 (三)——FindBugs 自定义规则入门
準備工作
由于 FindBugs 是分析編譯后的 class 文件,也就是字節碼文件。我們需要了解 FindBugs 底層的處理機制。根據FindBugs 官網文檔描述,FindBugs 使用了BCEL來分析 Java 字節碼文件。從 1.1 版本開始,FindBugs 也支持使用ASM字節碼框架來編寫 bug 探測器。
我們需要下載 FindBugs 源碼版用來新增自定義探測器:findbugs-3.0.1-source.zip
也需要下載 FindBugs 標準版:findbugs-3.0.1.zip,將 findbugs.jar 替換為我們的自定義版本后,運行查看結果。
自定義規則
自定義規則思路:
明確要定義的規則。
分析樣例代碼的字節碼內容。
編寫探測器。
將規則加入規則文件中。
1. 明確要定義的規則
我將以一個非常簡單的規則舉例:代碼中避免使用有類似 System.out 的輸出語句。
package main;
public class TestFindBugs {
public static void main(String[] args) {
System.out.println("123"); //bug
System.err.println("123"); //bug
}
}
2. 分析樣例代碼的字節碼內容
為了更方便的分析樣例代碼的字節碼內容,這里推薦一個 Eclipse 上用來查看 java 文件字節碼內容的插件:
Bytecode Outline
官網地址:http://andrei.gmxhome.de/bytecode/index.html
在安裝完成后,通過 Bytecode 工具編譯后的字節碼文件內容:
// 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
}
通過查看字節碼文件分析,我們找到了一些關鍵語句:
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
GETSTATIC java/lang/System.err : Ljava/io/PrintStream;
3. 編寫探測器
我們通過剛才找到的關鍵語句,結合我們的邏輯,進行探測器編寫:
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的輸出語句
*/
public class ForbiddenSystemClass extends OpcodeStackDetector {
BugReporter bugReporter;
public ForbiddenSystemClass(BugReporter bugReporter) {
this.bugReporter = bugReporter;
}
/**
* visit方法,在每次進入字節碼方法的時候調用 在每次進入新方法的時候清空標志位
*/
@Override
public void visit(Code obj) {
super.visit(obj);
}
/**
* 每掃描一條字節碼就會進入sawOpcode方法
*
* @param seen
* 字節碼的枚舉值
*/
@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. 將規則加入規則文件中
我們剛才在編寫探測器的時候,已經給定了規則的名稱CJ_SYSTEMCLASS。現在我們需要將這個規則添加在配置文件中。
配置 findbugs.xml:
配置 message.xml:
Default FindBugs plugin
This plugin contains all of the standard FindBugs detectors.
]]>
代碼不能出現System.out
請使用log日志形式打印
]]>
代碼不能出現System.out
{1}代碼不能出現System.out,請使用log形式輸出
不能使用System.out和System.err,請使用log
]]>
影響性能的輸出System.out
規則添加完成后,重新打包 findbugs.jar:
mvn clean install -Dmaven.test.skip=true
打包成功后,在可運行版本的 findbugs 中替換原來的/lib/findbugs.jar
執行 findbugs 命令,掃描樣例文件的 class 文件,查看運行結果:
在掃描結果中,可以看出確實掃描到了我們設定的問題語句。
使用 FindBugs 自定義規則成功!
參考文獻
360Qtest 團隊公眾號
關注公眾號,第一時間收到我們推送的新文章~
超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生總結
以上是生活随笔為你收集整理的java自定义findbugs规则_静态代码扫描 (三)——FindBugs 自定义规则入门的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java mapreduce 标准差_M
- 下一篇: java socket gui登录_ja