Eclipse中Find Bugs插件的學習

(轉載)

今天代碼質量再次強調java代碼提交SVN前要經過findBugs檢查,雖然根據菜單我也基本會有findBugs插件,但爲了更全面的學習、更高效的利用,我搜索學習了findbugs的用法。

檢查原理

Findbugs是一個靜態分析工具,它檢查類或者JAR 文件,將字節碼與一組缺陷模式進行對比以發現可能的問題。Findbugs自帶檢測器,其中有60餘種Bad practice,80餘種Correctness,1種 Internationalization,12種Malicious code vulnerability,27種Multithreaded correctness,23種Performance,43種Dodgy。我們還可以自己配置檢查規則(做哪些檢查,不做哪些檢查),也可以自己來實現獨有的校驗規則(用戶自定義特定的bug模式需要繼承它的接口,編寫自己的校驗類,屬於高級技巧)。

 白盒測試中的靜態檢查一般是檢查編碼標準規範,錯誤列表。編碼規範往往團隊會根據自己的經驗和風格進行設置一些規範。現在很多IDE工具都會在編輯代碼的時候實時的提醒是否符合代碼風格。錯誤列表,一般是代碼潛在的bug,由於某種代碼寫法雖然沒有語法錯誤,但是可能存在錯誤,比如會導致線程死鎖。這些都是錯誤列表應該檢查的。靜態檢查的可操作方式:

 1、代碼走查:

  程序員之間可以隔一定的時間抽取代碼進行走查。

  走查的時候根據彙總報告,把這些經驗匯成列表,作爲下次代碼走查的依據。

  該方式的特點是,手工、多人討論、操作簡單,但是效率會比較低。

 2、代碼掃描

使用軟件對我們的代碼進行掃描,查找出潛在的問題。現在有許多商業的工具能夠進行掃描,比如Parasoft JTest、Software Analyzer、pclint等工具,往往不同的工具會針對不同的語言。當然也有很多開源的工具。在這裏java方面主要推薦Findbugs。Findbugs可以在ANT/GUI/ECLIPSE三個環境中運行,同時也可以編寫自己的檢測器,功能比較完善。我們平時可以收集自己的或者是別人的開發經驗,把它做成檢測器來完善Findbugs的檢測體系。軟件掃描的特點是,機器掃描、效率高,但是沒不夠靈活,擴展比較負責。

Java靜態檢查工具對比

參考:http://blog.csdn.net/ml5271169588/article/details/6975701

http://www.cnblogs.com/hyddd/archive/2008/12/16/1356310.html

工具

目的

檢查項

FindBugs

檢查.class

基於Bug Patterns概念,查找javabytecode(.class文件)中的潛在bug

主要檢查bytecode中的bug patterns,如NullPoint空指針檢查、沒有合理關閉資源、字符串相同判斷錯(==,而不是equals)等

PMD

檢查源文件

檢查Java源文件中的潛在問題

主要包括:

空try/catch/finally/switch語句塊

未使用的局部變量、參數和private方法

空if/while語句

過於複雜的表達式,如不必要的if語句等

複雜類

CheckStyle

檢查源文件

主要關注格式

檢查Java源文件是否與代碼規範相符

主要包括:

Javadoc註釋

命名規範

多餘沒用的Imports

Size度量,如過長的方法

缺少必要的空格Whitespace

重複代碼

使用及配置

摘自:http://developer.51cto.com/art/200906/127165.htm

本文主要介紹在Eclipse中使用的情況

FindBugs是一個可以在Java程序中發現Bugs的程序。它是專門用來尋找處於"Bug Patterns"列表中的代碼的。Bug Patterns指很有可能是錯誤的代碼的實例。

打開Bug Details視圖Windows => Show View => Other… => FindBugs => BugDetails

在Package Explorer或Navigator視圖中,選中你的Java項目,右鍵,可以看到"Find Bugs"菜單項,子菜單項裏有"Find Bugs"和"Clear Bug Markers"兩項內容,如下圖所示:

我們建立一個簡單的測試文件Test.java 內容如下:

public class Test

{

private String[] name;

public String[] getName()

{

return name;

}

public void setName(String[] name)

{

this.name = name;

}

}

我們點中"Find Bugs",運行時會出現如下進度框:

運行結束後可以在Problems中看到增加了如下的警告信息內容

FindBugs運行後的警告信息內容不僅在Problems視圖中顯示,而且將標記在源代碼標記框中,在源代碼編輯器中我們可以看到警告標識,如下圖:

當光標指向你的警告信息的代碼上面時,就會有相應的錯誤提示信息,與Eclipse本身的錯誤或警告信息提示類似。

選中Problems視圖裏出現的相應問題,就會在代碼編輯器裏切換到相應的代碼上去,方便根據相應的提示信息進行代碼的修改。

在Problems視圖裏,選中相應的問題條目,右鍵,在彈出的菜單中,可以看到"Show Bug Details",如下圖所示:

點中它,會切換到Bug Details視圖上去,顯示更加詳細的提示信息。

當然,在代碼編輯窗口中,點擊帶有警告提示信息的圖標時,也會自動切換到Bud Details窗口去,查看詳細的警告信息,如下圖所示。

根據這裏詳細的信息,你可以得到FindBugs爲什麼會對你的代碼報警告信息,及相應的處理辦法,根據它的提示,你可以快速方便地進行代碼修改。

根據提示,我們將代碼修改成如下,再運行就不會報有警告信息了。

public class Test

{

private String[] name;

public String[] getName()

{

String[] temp = name;

return temp;

}

public void setName(String[] name)

{

String[] temp = name;

this.name = temp;

}

}

配置FindBugs

選擇你的項目,右鍵 => Properties => FindBugs =>

可以配置的信息包括如上圖所示的四個選項的相關設置:

1. Run FindBugs Automatically開關

當此項選中後,FindBugs將會在你修改Java類時自動運行,如你設置了Eclipse自動編譯開關後,當你修改完Java文件保存,FindBugs就會運行,並將相應的信息顯示出來。

當此項沒有選中,你只能每次在需要的時候自己去運行FindBugs來檢查你的代碼。

2. Minimum priority to report選擇項

這個選擇項是讓你選擇哪個級別的信息進行顯示,有Low、Medium、High三個選擇項可以選擇,很類似於Log4J的級別設置啦。 比如:

你選擇了High選擇項,那麼只有是High級別的提示信息纔會被顯示。

你選擇了Medium選擇項,那麼只有是Medium和High級別的提示信息纔會被顯示。

你選擇了Low選擇項,那麼所有級別的提示信息都會被顯示。

3. Enable bug categories選擇項

在這裏是一些顯示Bug分類的選擇:

Correctness關於代碼正確性相關方面的

Performance關於代碼性能相關方面的

Internationalization關於代碼國際化相關方面的

Multithreaded correctness關於代碼多線程正確性相關方面的

Style關於代碼樣式相關方面的

Malicious code vulnerability關於惡意破壞代碼相關方面的

比如:如果你把Style的檢查框去掉不選擇中它,那麼與Style分類相關的警告信息就不會顯示了。其它的類似。

4. Select bug patterns to check for選擇項

在這裏你可以選擇所要進行檢查的相關的Bug Pattern條目

可以從Bug codes、Detector name、Detector description中看到相應的是要檢查哪些方面的內容,你可以根據需要選擇或去掉相應的 檢查條件。

三、詳細說明

Findbugs是一個靜態分析工具,它檢查類或者JAR 文件,將字節碼與一組缺陷模式進行對比以發現可能的問題。Findbugs自帶檢測器,其中有60餘種Bad practice,80餘種Correctness,1種 Internationalization,12種Malicious code vulnerability,27種Multithreaded correctness,23種Performance,43種Dodgy。

Bad practice 壞的實踐

一些不好的實踐,下面列舉幾個:

HE: 類定義了equals(),卻沒有hashCode();或類定義了equals(),卻使用

Object.hashCode();或類定義了hashCode(),卻沒有equals();或類定義了hashCode(),卻使用Object.equals();類繼承了equals(),卻使用Object.hashCode()。

SQL:Statement 的execute方法調用了非常量的字符串;或Prepared Statement是由一個非常量的字符串產生。

DE: 方法終止或不處理異常,一般情況下,異常應該被處理或報告,或被方法拋出。

Correctness 一般的正確性問題

可能導致錯誤的代碼,下面列舉幾個:

NP: 空指針被引用;在方法的異常路徑裏,空指針被引用;方法沒有檢查參數是否null;null值產生並被引用;null值產生並在方法的異常路徑被引用;傳給方法一個聲明爲@NonNull的null參數;方法的返回值聲明爲@NonNull實際是null。

Nm: 類定義了hashcode()方法,但實際上並未覆蓋父類Object的hashCode();類定義了tostring()方法,但實際上並未覆蓋父類Object的toString();很明顯的方法和構造器混淆;方法名容易混淆。

SQL:方法嘗試訪問一個Prepared Statement的0索引;方法嘗試訪問一個ResultSet的0索引。

UwF:所有的write都把屬性置成null,這樣所有的讀取都是null,這樣這個屬性是否有必要存在;或屬性從沒有被write。

Internationalization 國際化

當對字符串使用upper或lowercase方法,如果是國際的字符串,可能會不恰當的轉換。

Malicious code vulnerability 可能受到的惡意攻擊

如果代碼公開,可能受到惡意攻擊的代碼,下面列舉幾個:

FI: 一個類的finalize()應該是protected,而不是public的。

MS:屬性是可變的數組;屬性是可變的Hashtable;屬性應該是package protected的。

Multithreaded correctness 多線程的正確性

多線程編程時,可能導致錯誤的代碼,下面列舉幾個:

ESync:空的同步塊,很難被正確使用。

MWN:錯誤使用notify(),可能導致IllegalMonitorStateException異常;或錯誤的

使用wait()。

No: 使用notify()而不是notifyAll(),只是喚醒一個線程而不是所有等待的線程。

SC: 構造器調用了Thread.start(),當該類被繼承可能會導致錯誤。

Performance 性能問題

可能導致性能不佳的代碼,下面列舉幾個:

DM:方法調用了低效的Boolean的構造器,而應該用Boolean.valueOf(…);用類似

Integer.toString(1) 代替new Integer(1).toString();方法調用了低效的float的構造器,應該用靜態的valueOf方法。

SIC:如果一個內部類想在更廣泛的地方被引用,它應該聲明爲static。

SS: 如果一個實例屬性不被讀取,考慮聲明爲static。

UrF:如果一個屬性從沒有被read,考慮從類中去掉。

UuF:如果一個屬性從沒有被使用,考慮從類中去掉。

Dodgy 危險的

具有潛在危險的代碼,可能運行期產生錯誤,下面列舉幾個:

CI: 類聲明爲final但聲明瞭protected的屬性。

DLS:對一個本地變量賦值,但卻沒有讀取該本地變量;本地變量賦值成null,卻沒有讀取該本地變量。

ICAST: 整型數字相乘結果轉化爲長整型數字,應該將整型先轉化爲長整型數字再相乘。

INT:沒必要的整型數字比較,如X <= Integer.MAX_VALUE。

NP: 對readline()的直接引用,而沒有判斷是否null;對方法調用的直接引用,而方法可能返回null。

REC:直接捕獲Exception,而實際上可能是RuntimeException。

ST: 從實例方法裏直接修改類變量,即static屬性。

可參考:http://blog.csdn.net/fanyuna/article/details/6860198

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章