前言
FindBugs 同樣是用來檢測 Java 程式的工具,其檢測的對象是 Byte Code (class 或是 jar 檔)。儘管如此,FindBugs 依舊是屬於靜態分析的方式。FindBugs 如其名,主要是利用 Bug Patterns 的概念,找尋出程式中有問題 (Bugs) 的程式碼 。在其官方的網站中提到 Bug Patterns 的產生可能有下列因素:
- 程式語言本身不容易使用的功能 (Difficult language features)
- 被誤用的 API (Misunderstood API methods)
- 當程式碼在維護時,不變的條件被誤解了 (Misunderstood invariants when code is modified during maintenance)
- 其他常見的錯誤,例如打錯字、或是使用了錯誤的布林運算元 (Garden varieity mistakes: typos, use of the wrong boolean operator)
FindBugs 本身提供完整的 GUI 介面,讓使用者可以很方便地進行檢測的工作。因為 FindBugs 主要使用 Java 進行開發,所以可以運行於各種的作業系統上。雖然 FindBugs 是針對 ByteCode 進行掃描,但是在 GUI 中我們可以指定原始程式碼所在的目錄。如此一來, FindBugs 就會自動將發現問題的 ByteCode 與原始程式碼自動連結並加以顯示。
點選 Bug 後可以自動顯示出 Bug 所在的程式碼
除了 GUI 的操作方式外,FindBugs 也支援 Ant 的開發環境。而在與 IDE 整合方面,則僅提供 Eclipse 的 Plug-in。也因為 FindBugs 支援 Eclipse 的 Plug-in,接下來我會直接使用 Eclipse 的 Plug-in 作為範例說明。不過在此之前,我先提醒一下在使用 GUI 時有兩個需要特別注意的地方。第一個是如果在進行分析時進度忽然停滯不動,有可能是因為記憶體使用量已經超過限制,此時需要增加 JVM 記憶體的使用量 (-Xmx)。另外一個就是在 Microsoft Windows 下我一直沒有辦法正確的連結到原始程式碼。
安裝 Eclipse 的 Plug-in
- 選取功能選單的 Help –> Install New Software。
- 點選 “Add…” 按鈕,輸入下列資料後按下按鈕 “OK”。
- 在 Work with 的下拉選單中選取 FindBugs – http://findbugs.cs.umd.edu/eclipse ,點選後需要等待一段時間。
- 點選 FindBugs 後按下按鈕 “Next >”,點選後需要等待一段時間。
- 選取 FindBugs Feature 後按下按鈕 “Next >”。
- 選取 I accept the terms of the license agreement 後按下按鈕 “Finish”。
- 等待安裝畫面執行完畢。
- 安裝完畢後按下 “Yes” 按鈕重開 Eclipse 以使 FindBugs Plug-in 生效。
使用 FindBugs 檢測 Struts 程式碼
- 在程式碼 (或專案) 的目錄下使用滑鼠右鍵叫出功能選單,選取 Find Bugs –> Find Bugs。
- 等候 Find Bugs 檢測完畢。
- 檢測完畢後會跳出一個視窗詢問是否切換至 FindBugs 的 perspective,先選 Yes。
- 在FindBugs perspective的左上角出現 Bug Explorer,將發現的問題依據不同的原因加以分類,可以很快的了解有哪些問題需要進一步處理。
- 但是 FindBugs perspective 在操作上有些不順暢的地方,右邊的 view 也有被切掉的情形,因此我們切換回 Java perspective。
利用右上方的按鈕切換回Java perspective
- FindBugs 的檢測結果顯示於 Problems view。
- 在發現的 Bug 上點選右鍵叫出功能選單,選取 Properties 以顯示問題的詳細資訊。
- Message 欄位顯示問題的描述。
- Category 欄位顯示 Bug 的分類
- 上述的資訊雖然很完整,但是卻過於分散不容易閱讀。我們可以利用在警告圖示點選右鍵的功能選單上,選取 Show Bug Details 以顯示 Bug 相關資訊。
- 雖然顯示的資訊較少,但是可以一眼看到 Bug 的類別與說明,方便了解問題與後續處理方式之判斷。
設定 FindBugs 的檢測項目
我們可以利用專案的 Properites 設定畫面,進行 FindBugs 的相關設定。主要設定項目包含是否自動執行 FindBugs 檢測項目 (Run automatically)以及檢測項目的相關設定。雖然自動執行 FindBugs 檢測項目相當方便,但是因為 FindBugs 檢測需要一段不算短的時間,所以勾選時請加以三思。如果有必要,請記得讓 FindBugs 的檢測在背景執行,設定方式為在 FindBugs 的執行畫面選取 Always run in background。檢測項目設定部分可以指定哪些檢測項目需要執行,這樣的設計比 PMD 使用上來的更為方便。此外也可以設定報表與過濾器 (Filter) 相關之選項,過濾器主要是用來告知 FindBugs 那些項目 (如類別) 不需要統計在結果的報告中。
FindBugs 設定畫面 (專案的 Properties 畫面)
當使用自動執行 FindBugs 時,請勾選 Always run in background 以免等待過長的時間。
Bugs 的處理
透過 FindBugs 找出問題後,我們同樣需要確認是否需要進行修正。如果我們認定不需要修正,那麼有下列幾個方法可以告知 FindBugs 不需要把這個問題放入警告中。
- 利用過濾器的機制。使用方法為在特定的問題上點選滑鼠右鍵,然後執行 Toggle Filter –> This Specific Bug Pattern。再次點選可以讓此類問題再次被加以警告。實際上此操作方法將使得同一種類的問題都被加以忽視,而不是針對單一問題,所以使用上並不方便。過濾器除了可以透過此一介面加以設定外,也可以在專案設定畫面中指定外部的設定檔。此外部檔案除可同步用於 Ant 的環境下外,而且可做更細緻的設定,而非僅能針對同一類別下的所有問題。
- 利用 Annotations 的機制,宣告哪些函式/類別/參數等不需要提出警告 (SuppressWarnings)。使用上除了無法透過 Eclipse Plugin 操作介面的指令直接產生外,同樣也無法針對單一的問題加以宣告。
宣告 equals 函式不要產生警告訊息 - 透過 GUI 提供的功能,我們可以將找到的問題加以分類,並且填上相關說明。在使用上最為方便,功能也最為完整。但是卻僅能操作於 GUI 的環境,而無法在 Eclipse Plug-in 加以使用。這些資訊可以連同檢測結果一併儲存下來,以便日後的檢視與分析。
報表
FindBugs 提供不同的分析能力,包含能夠將多個檢測結果加以整合 (union bugs)、統計多次的檢測結果 (compute bug history)、選取特定的問題 (filter bugs)、計算問題的密度 (defect density)等等。這些工作可以透過 Ant 加以執行,另外也提供命令列的執行方式 (for /bin/sh)。FindBugs 在這方面的能力優於 PMD 所提供的功能,尤其是統計多次檢測結果的能力,可以方便管理者做追蹤的動作。
Annotations
Annotations 除了可以用來告知 FindBugs 哪些項目不需要進行警告外 (SuppressWarnings),還可以告知 FindBugs 那些項目應該做何檢視。我們用一個假想的例子加以說明。在範例程式中,首先我們宣告 print 函示的參數 (sb) 有可能是 null (CheckForNull),所以 FindBugs 會發現到我們使用 sb 時並沒有先做是否為 null 的判斷,因此產生了警告的訊息。除此之外,我們也宣告呼叫 reverse 這個函數的回傳值需要被檢查 (CheckReturnValue)。同樣的,因為我們的程式在呼叫 reverse 時並沒有檢查回傳值,所以產生了警告的訊息。透過 Annotations 的機制,可以強制 FindBugs 進行我們所需的檢查項目,以避免一些將來可能發生的潛在問題。
結語
FindBugs 在進行檢測時所花費的時間比較多 (與 Eclipse 或 PMD 相較),其檢測出來的問題數也相對較少。這並不代表 FindBugs 的效果較差,只能說是目的不同。我個人覺得最可惜的是在與 IDE 整合方面仍有很大的改進空間。唯一支援的 Eclipse Plug-in,在使用上連問題的處理都無法有效進行,倒是在資訊的呈現相當詳盡。既然官方網站也說 Eclipse Plug-in 還在測試階段,就讓我們對其日後的表現拭目以待。在此之前,使用 GUI 來進行檢測是一個折衷的辦法。此外,報表的功能可以做歷史記錄的追蹤,這點對於程式碼的管理有其一定的作用。同樣可惜的是必須透過 Ant (或命令列) 的形式才有辦法產生報表,在使用上的親和力同樣略嫌不足。