バグデータベースへの高機能の問い合わせ機能、および、調査対象のコードの複数のバージョンにわたる警告の追跡記録機能を、 FindBugs は内蔵しています。これらを使って次のようなことができます。すなわち、いつバグが最初持ち込まれたかを捜し出すこと、最終リリース以後持ち込まれた警告の分析を行うこと、または、無限再起ループの数を時間軸でグラフにすることです。
これらの技術は、 FindBugs が警告の保存に使う XML 書式を使用します。これらの XML ファイルは、通常、特定の 1 分析に対する警告が入れられています。しかしそれらには、一連のソフトウェアのビルドやバージョンに対する分析結果を格納することもできます。
すべての FindBugs XML バグデータベースには、バージョン名とタイム・スタンプ が入れられています。FindBugs は分析が行われるファイルの更新時刻からタイム・スタンプを計算します (例えば、タイム・スタンプはクラスファイルの生成時刻になるようになっています。分析が行われた時刻ではありません) 。各々のバグデータベースには、バージョン名も入れられています。バージョン名とタイム・スタンプは、 setBugDatabaseInfo (「setBugDatabaseInfo」) コマンドを使用して手動で設定することもできます。
複数バージョンを格納するバグデータベースにおいては、分析されるコードの各バージョンごとにシーケンス番号が割り当てられます。これらのシーケンス番号は単に 0 から始まる連続する整数値です (例えば、 4 つのコードバージョンを格納するバグデータベースには、バージョン 0~3 が入れられます) 。バグデータベースにはまた、各バージョンの名前とタイム・スタンプがそれぞれ記録されます。filterBugs コマンドを使用すると、シーケンス番号、バージョン名またはタイム・スタンプからバージョンを参照することができます。
1 バージョンを格納するバグデータベースの集合から、 1 個の複数バージョンバグデータベースを作成することができます。また、複数バージョンバグデータベースに対して、それ以後に作成された 1 バージョンのバグデータベースを結合することができます。
これらのコマンドのいくつかは、 ant タスクとして実行することができます。コマンドの実行方法および属性・引数の詳細は、以下を参照してください。以下のすべての例においては、 findbugs.lib
refid
が正しく設定されていることを前提としています。設定方法の一例を次に示します :
<!-- findbugs タスク定義 --> <property name="findbugs.home" value="/your/path/to/findbugs" /> <path id="findbugs.lib"> <fileset dir="${findbugs.home}/lib"> <include name="findbugs-ant.jar"/> </fileset> </path>
FindBugs データ・マイニング ツールはすべてコマンドラインから実行することができます。また、いくつかのより有用なコマンドは、 ant ビルドファイルから実行することができます。
コマンドラインツールについて簡単に説明します :
別のクラスに対する別個の分析結果を結合します。
複数バージョンから得られた複数のバグ警告を、マージして 1 個の複数バージョンバグデータベースにします。これを使って、既存の複数バージョンバグデータベースに更にバージョンを追加したり、 1 バージョンを格納するバグデータベースの集合から 1 個の複数バージョンバグデータベースを作成したり、できます。
リビジョン名やタイム・スタンプなどの情報を XML データベースに設定します。
XML データベースにあるリビジョン名やタイム・スタンプなどの情報を一覧表示します。
バグデータベースの部分集合を選択します。
複数バージョンバグデータベースの各バージョン毎の警告数を一覧にした表を作成します。
プロジェクト全体およびクラス毎・パッケージ毎の不良密度 (1000 NCSS 毎の警告数) に関する情報を一覧表示します。
XML 形式のバグ警告を、 1 行 1 バグのテキスト形式、または、HTML形式に変換します。
分析するのにアプリケーションの jar ファイルを分割している場合、このコマンドを使用することで、別個に生成された XML バグ警告ファイルをすべての警告を含んでいる 1 つの ファイルにすることができます。
同じファイルの異なるバージョンを分析した結果を結合する場合は、このコマンドを使用しないでください。代わりに computeBugHistory を使用してください。
XML ファイルは、コマンドラインで指定してください。結果は、標準出力に送られます。
このコマンドを使用することで、分析するソフトウェアの異なるビルドまたはバージョンの情報を含むバグデータベースを生成することができます入力として提供したファイルの 1 番目のファイルから履歴が取得されます。後に続くファイルは 1 バージョンのバグデータベースであるようにしてください (もし、履歴を持っていたとしても無視されます) 。
デフォルトでは、結果は標準出力に送られます。
この機能は、 ant からも使用することができます。まず次に示すように、ビルドファイルに computeBugHistory を taskdef で定義します :
<taskdef name="computeBugHistory" classname="edu.umd.cs.findbugs.anttask.ComputeBugHistoryTask"> <classpath refid="findbugs.lib" /> </taskdef>
この ant タスクに指定できる属性を、下表に一覧で示します。入力ファイルを指定するには、 <datafile>
要素を入れ子にして入れてください。次に、例を示します:
<computeBugHistory home="${findbugs.home}" ...> <datafile name="analyze1.xml"/> <datafile name="analyze2.xml"/> </computeBugHistory>
表12.1 computeBugHistory コマンドのオプション一覧
コマンドラインオプション | Ant 属性 | 目的 |
---|---|---|
-output <file> | output="<file>" | 出力結果を保存するファイル名を指定します。 (同時に入力ファイルにもなりえます) |
-overrideRevisionNames[:truth] | overrideRevisionNames="[true|false]" | ファイル名から算出されるそれぞれのバージョン名を指定変更します。 |
-noPackageMoves[:truth] | noPackageMoves="[true|false]" | パッケージを移動したクラスがある場合、当該クラスの警告は別の存在として扱われます。 |
-preciseMatch[:truth] | preciseMatch="[true|false]" | バグパターンが正確に一致することを要求します。 |
-precisePriorityMatch[:truth] | precisePriorityMatch="[true|false]" | 優先度が正確に一致した場合のみ警告が同一であると判断されます。 |
-quiet[:truth] | quiet="[true|false]" | エラーが発生しない限り、標準出力には何も表示されません。 |
-withMessages[:truth] | withMessages="[true|false]" | 出力 XML に人間が読むことができるバグメッセージが含まれます。 |
このコマンドを使用することで、 FindBugs XML 警告ファイルから一部分を選び出して新規 FindBugs 警告ファイルに選択された部分を書き込むことができます。
このコマンドには、オプション群に続いて 0 個から 2 個の findbugs xml バグファイルを指定することができます。
ファイル名をひとつも指定しない場合は、標準入力から読んで標準出力に出力されます。ファイル名を 1 個 指定した場合は、指定したファイルから読んで標準出力に出力されます。ファイル名を 2 個 指定した場合は、 1 番目に指定したファイルから読んで 2 番目に指定したファイルに出力されます。
この機能は、 ant からも使用することができます。まず次に示すように、ビルドファイルに filterBugs を taskdef で定義します :
<taskdef name="filterBugs" classname="edu.umd.cs.findbugs.anttask.FilterBugsTask"> <classpath refid="findbugs.lib" /> </taskdef>
この ant タスクに指定できる属性を、下表に一覧で示します。入力ファイルを指定するには、 input
属性を使用するか、 <datafile>
要素を入れ子にして入れてください。次に、例を示します:
<filterBugs home="${findbugs.home}" ...> <datafile name="analyze.xml"/> </filterBugs>
表12.2 filterBugs コマンドのオプション一覧
コマンドラインオプション | Ant 属性 | 目的 |
---|---|---|
input="<file>" | 入力ファイルを指定します。 | |
output="<file>" | 出力ファイルを指定します。 | |
-not | not="[true|false]" | フィルターのスイッチを反転します。 |
-withSource[:truth] | withSource="[true|false]" | ソースが入手可能な警告のみ出力されます。 |
-exclude <filter file> | exclude="<filter file>" | フィルターに一致するバグが除外されます。 |
-include <filter file> | include="<filter file>" | フィルターに一致するバグのみを含まれます。 |
-annotation <text> | annotation="<text>" | 手で入力した注釈に指定した文言を含む警告のみ出力されます。 |
-after <when> | after="<when>" | 指定したバージョンより後に初めて出現した警告のみ出力されます。 |
-before <when> | before="<when>" | 指定したバージョンより前に初めて出現した警告のみ出力されます。 |
-first <when> | first="<when>" | 指定したバージョンに初めて出現した警告のみ出力されます。 |
-last <when> | last="<when>" | 指定したバージョンが出現した最後である警告のみ出力されます。 |
-fixed <when> | fixed="<when>" | 指定したバージョンの前回のバージョンが出現した最後である警告のみ出力されます。 (-last に優先します)。 |
-present <when> | present="<when>" | 指定したバージョンに存在する警告のみ出力されます。 |
-absent <when> | absent="<when>" | 指定したバージョンに存在しない警告のみ出力されます。 |
-active[:truth] | active="[true|false]" | 最終通番に存在する警告のみ出力されます。 |
-introducedByChange[:truth] | introducedByChange="[true|false]" | 存在するクラスの変更によってもたらされた警告のみ出力されます。 |
-removedByChange[:truth] | removedByChange="[true|false]" | 存在するクラスの変更によって除去された警告のみ出力されます。 |
-newCode[:truth] | newCode="[true|false]" | 新クラスの追加によってもたらされた警告のみ出力されます。 |
-removedCode[:truth] | removedCode="[true|false]" | クラスの削除によって除去された警告のみ出力されます。 |
-priority <level> | priority="<level>" | 指定した優先度以上の優先度をもつ警告のみ出力されます。 |
-maxRank <rank> | rank="[1..20]" | allow only warnings with this rank or lower |
-class <pattern> | class="<class>" | 指定したパターンに一致する主クラスをもつ警告のみ出力されます。 |
-bugPattern <pattern> | bugPattern="<pattern>" | 指定したパターンに一致するバグ種別をもつ警告のみ出力されます。 |
-category <category> | category="<category>" | 指定した文字列で始まるカテゴリーの警告のみ出力されます。 |
-designation <designation> | designation="<designation>" | 指定したバグ分類指定をもつ警告のみ出力されます。 (例、 -designation SHOULD_FIX) |
-withMessages[:truth] | withMessages="[true|false]" | テキストメッセージを含んだ XML が生成されます。 |
このコマンドを使用することで、複数バージョンバグデータベースの各バージョン毎の警告数を一覧にした表を作成することができます。
この機能は、 ant からも使用することができます。まず次に示すように、ビルドファイルに mineBugHistory を taskdef で定義します :
<taskdef name="mineBugHistory" classname="edu.umd.cs.findbugs.anttask.MineBugHistoryTask"> <classpath refid="findbugs.lib" /> </taskdef>
この ant タスクに指定できる属性を、下表に一覧で示します。入力ファイルを指定するには、 input
属性を使用するか、 <datafile>
要素を入れ子にして入れてください。次に、例を示します:
<mineBugHistory home="${findbugs.home}" ...> <datafile name="analyze.xml"/> </mineBugHistory>
表12.3 mineBugHistory コマンドのオプション一覧
コマンドラインオプション | Ant 属性 | 目的 |
---|---|---|
input="<file>" | 入力ファイルを指定します。 | |
output="<file>" | 出力ファイルを指定します。 | |
-formatDates | formatDates="[true|false]" | データがテキスト形式で描画されます。 |
-noTabs | noTabs="[true|false]" | タブの代わりに複数スペースでカラムが区切られます (下記参照)。 |
-summary | summary="[true|false]" | 最新 10 件の変更の要約が出力されます。 |
-noTabs
出力を使うことで、固定幅フォントのシェルで読み易くなります。数値カラムは右寄せされるので、スペースがカラム値の前に挿入されます。また、このオプションを使用した場合、 -formatDates
を指定したときに要約の日付を描画するのに空白が埋め込まれなくなります。
出力される表は、 (-noTabs
が無ければ) タブ区切りで次に示すカラムから成ります :
表12.4 mineBugHistory 出力のカラム一覧
表題 | 目的 |
---|---|
seq | シーケンス番号 (0 始まりの連続した整数値) |
version | バージョン名 |
time | リリースされた日時 |
classes | 分析されたクラス数 |
NCSS | コメント文を除いた命令数 (Non Commenting Source Statements) |
added | 前回のバージョンに存在したクラスにおける新規警告数 |
newCode | 前回のバージョンに存在しなかったクラスにおける新規警告数 |
fixed | 現在のバージョンに存在するクラスにおける除去された警告数 |
removed | 現在のバージョンに存在しないクラスの前回のバージョンにおける警告数 |
retained | 現在のバージョンと前回のバージョンの両方に存在する警告の数 |
dead | 以前のバージョンに存在したが現在のバージョンにも直前のバージョンにも存在しない警告の数 |
active | 現在のバージョンに存在する警告総数 |
このコマンドを使用することで、プロジェクト全体およびクラス毎・パッケージ毎の不良密度 (1000 NCSS 毎の警告数) に関する情報を一覧表示できます。標準入力から読み込む場合はファイル指定なしで、そうでなければ、コマンドラインでファイルを指定して、このコマンドを実行します。
出力される表は、次に示すカラムから成ります。また、プロジェクト全体情報の行、および、4 個以上の警告を含んでいる各パッケージ情報または各クラス情報の行も出力されます。
表12.5 defectDensity 出力のカラム一覧
表題 | 目的 |
---|---|
kind | プロジェクト (project)、パッケージ (package) またはクラス (class) |
name | プロジェクト、パッケージまたはクラスの名前 |
density | 1000 NCSS 毎の警告数 |
bugs | 警告数 |
NCSS | コメント文を除いた命令数 (Non Commenting Source Statements) |
このコマンドを使用することで、XML 形式のバグ警告を、 1 行 1 バグのテキスト形式、または、HTML形式に変換することができます。
この機能は、 ant からも使用することができます。まず次に示すように、ビルドファイルに convertXmlToText を taskdef で定義します :
<taskdef name="convertXmlToText" classname="edu.umd.cs.findbugs.anttask.ConvertXmlToTextTask"> <classpath refid="findbugs.lib" /> </taskdef>
この ant タスクに指定できる属性を、下表に一覧で示します。
表12.6 convertXmlToText コマンドのオプション一覧
コマンドラインオプション | Ant 属性 | 目的 |
---|---|---|
input="<filename>" | 入力ファイルを指定します。 | |
output="<filename>" | 出力ファイルを指定します。 | |
-longBugCodes | longBugCodes="[true|false]" | 2 文字のバグ略称の代わりに、省略なしのバグパターンコードを使用します。 |
format="text" | プレーンテキストの出力が作成されます。1 行につき 1 つのバグが出力されます。コマンドライン時のデフォルトです。 | |
-html[:stylesheet] | format="html:<stylesheet>" | 指定されたスタイルシートを使用して出力が作成されます (下記参照) 。省略した場合は、 default.xsl が使用されます。 |
-html/format オプションには、plain.xsl 、 default.xsl 、 fancy.xsl 、 fancy-hist.xsl または ユーザ自身が作成した XSL スタイルシートのいずれかを指定することができます。オプション名をよそに、 html 以外の形式を出力するスタイルシートを指定することもできます。FindBugs に含まれているスタイルシート(上述)以外のスタイルシートを使用する場合は、オプション -html/format で当該スタイルシートへのパスまたは URL を指定してください。
このコマンドを使用することで、指定したバグ警告にメタ情報を設定することができます。このコマンドには次に示すオプションがあります:
この機能は、 ant からも使用することができます。まず次に示すように、ビルドファイルに setBugDatabaseInfo を taskdef で定義します :
<taskdef name="setBugDatabaseInfo" classname="edu.umd.cs.findbugs.anttask.SetBugDatabaseInfoTask"> <classpath refid="findbugs.lib" /> </taskdef>
この ant タスクに指定できる属性を、下表に一覧で示します。入力ファイルを指定するには、 input
属性を使用するか、 <datafile>
要素を入れ子にして入れてください。次に、例を示します:
<setBugDatabaseInfo home="${findbugs.home}" ...> <datafile name="analyze.xml"/> </setBugDatabaseInfo>
表12.7 setBugDatabaseInfo オプション一覧
コマンドラインオプション | Ant 属性 | 目的 |
---|---|---|
input="<file>" | 入力ファイルを指定します。 | |
output="<file>" | 出力ファイルを指定します。 | |
-name <name> | name="<name>" | 最新リビジョンの名前を設定します。 |
-timestamp <when> | timestamp="<when>" | 最新リビジョンのタイム・スタンプを設定します。 |
-source <directory> | source="<directory>" | ソースを検索するディレクトリーを追加指定します。 |
-findSource <directory> | findSource="<directory>" | 指定したディレクトリー内を検索して関連するソースの場所を追加します。 |
-suppress <filter file> | suppress="<filter file>" | 指定したファイルに一致する警告を抑止します (以前に指定した抑止設定は置き換えられます)。 |
-withMessages | withMessages="[true|false]" | XMLにテキストメッセージを追加します。 |
-resetSource | resetSource="[true|false]" | ソース検索パスをすべて削除します。 |
このコマンドの実行においては、コマンドラインで 0 個以上の xml バグデータベースファイル名を指定します。ファイル名を1つも指定しなければ、標準出力から読み込みを行いテーブルのヘッダーは生成されません。
このコマンドには 1 つだけオプションがあります : -formatDates
を指定するとテキスト形式でデータが描画されます。
出力される表は、各バグデータベースごとに行を持ち、次に示すカラムから成ります :
表12.8 listBugDatabaseInfo カラム一覧
カラム | 目的 |
---|---|
version | バージョン名 |
time | リリースされた日時 |
classes | 分析されたクラス数 |
NCSS | コメント文を除いた命令数 (Non Commenting Source Statements) |
total | 全警告数 |
high | 優先度(高)の警告の総数 |
medium | 優先度(中)の警告の総数 |
low | 優先度(低)の警告の総数 |
filename | データベースのファイル名 |
以下はすべて、 jdk1.6.0-b12, jdk1.6.0-b13, ..., jdk1.6.0-b60 のディレクトリに対してコマンドを実行しています。
以下のコマンドを実行してみます :
computeBugHistory jdk1.6.0-b* | filterBugs -bugPattern IL_ | mineBugHistory -formatDates
すると、次のような出力が行われます :
seq version time classes NCSS added newCode fixed removed retained dead active 0 jdk1.6.0-b12 "Thu Nov 11 09:07:20 EST 2004" 13128 811569 0 4 0 0 0 0 4 1 jdk1.6.0-b13 "Thu Nov 18 06:02:06 EST 2004" 13128 811570 0 0 0 0 4 0 4 2 jdk1.6.0-b14 "Thu Dec 02 06:12:26 EST 2004" 13145 811786 0 0 2 0 2 0 2 3 jdk1.6.0-b15 "Thu Dec 09 06:07:04 EST 2004" 13174 811693 0 0 1 0 1 2 1 4 jdk1.6.0-b16 "Thu Dec 16 06:21:28 EST 2004" 13175 811715 0 0 0 0 1 3 1 5 jdk1.6.0-b17 "Thu Dec 23 06:27:22 EST 2004" 13176 811974 0 0 0 0 1 3 1 6 jdk1.6.0-b19 "Thu Jan 13 06:41:16 EST 2005" 13176 812011 0 0 0 0 1 3 1 7 jdk1.6.0-b21 "Thu Jan 27 05:57:52 EST 2005" 13177 812173 0 0 0 0 1 3 1 8 jdk1.6.0-b23 "Thu Feb 10 05:44:36 EST 2005" 13179 812188 0 0 0 0 1 3 1 9 jdk1.6.0-b26 "Thu Mar 03 06:04:02 EST 2005" 13199 811770 0 0 0 0 1 3 1 10 jdk1.6.0-b27 "Thu Mar 10 04:48:38 EST 2005" 13189 812440 0 0 0 0 1 3 1 11 jdk1.6.0-b28 "Thu Mar 17 02:54:22 EST 2005" 13185 812056 0 0 0 0 1 3 1 12 jdk1.6.0-b29 "Thu Mar 24 03:09:20 EST 2005" 13117 809468 0 0 0 0 1 3 1 13 jdk1.6.0-b30 "Thu Mar 31 02:53:32 EST 2005" 13118 809501 0 0 0 0 1 3 1 14 jdk1.6.0-b31 "Thu Apr 07 03:00:14 EDT 2005" 13117 809572 0 0 0 0 1 3 1 15 jdk1.6.0-b32 "Thu Apr 14 02:56:56 EDT 2005" 13169 811096 0 0 0 0 1 3 1 16 jdk1.6.0-b33 "Thu Apr 21 02:46:22 EDT 2005" 13187 811942 0 0 0 0 1 3 1 17 jdk1.6.0-b34 "Thu Apr 28 02:49:00 EDT 2005" 13195 813488 0 1 0 0 1 3 2 18 jdk1.6.0-b35 "Thu May 05 02:49:04 EDT 2005" 13457 829837 0 0 0 0 2 3 2 19 jdk1.6.0-b36 "Thu May 12 02:59:46 EDT 2005" 13462 831278 0 0 0 0 2 3 2 20 jdk1.6.0-b37 "Thu May 19 02:55:08 EDT 2005" 13464 831971 0 0 0 0 2 3 2 21 jdk1.6.0-b38 "Thu May 26 03:08:16 EDT 2005" 13564 836565 0 0 0 0 2 3 2 22 jdk1.6.0-b39 "Fri Jun 03 03:10:48 EDT 2005" 13856 849992 0 1 0 0 2 3 3 23 jdk1.6.0-b40 "Thu Jun 09 03:30:28 EDT 2005" 15972 959619 0 2 0 0 3 3 5 24 jdk1.6.0-b41 "Thu Jun 16 03:19:22 EDT 2005" 15972 959619 0 0 0 0 5 3 5 25 jdk1.6.0-b42 "Fri Jun 24 03:38:54 EDT 2005" 15966 958581 0 0 0 0 5 3 5 26 jdk1.6.0-b43 "Thu Jul 14 03:09:34 EDT 2005" 16041 960544 0 0 0 0 5 3 5 27 jdk1.6.0-b44 "Thu Jul 21 03:05:54 EDT 2005" 16041 960547 0 0 0 0 5 3 5 28 jdk1.6.0-b45 "Thu Jul 28 03:26:10 EDT 2005" 16037 960606 0 0 1 0 4 3 4 29 jdk1.6.0-b46 "Thu Aug 04 03:02:48 EDT 2005" 15936 951355 0 0 0 0 4 4 4 30 jdk1.6.0-b47 "Thu Aug 11 03:18:56 EDT 2005" 15964 952387 0 0 1 0 3 4 3 31 jdk1.6.0-b48 "Thu Aug 18 08:10:40 EDT 2005" 15970 953421 0 0 0 0 3 5 3 32 jdk1.6.0-b49 "Thu Aug 25 03:24:38 EDT 2005" 16048 958940 0 0 0 0 3 5 3 33 jdk1.6.0-b50 "Thu Sep 01 01:52:40 EDT 2005" 16287 974937 1 0 0 0 3 5 4 34 jdk1.6.0-b51 "Thu Sep 08 01:55:36 EDT 2005" 16362 979377 0 0 0 0 4 5 4 35 jdk1.6.0-b52 "Thu Sep 15 02:04:08 EDT 2005" 16477 979399 0 0 0 0 4 5 4 36 jdk1.6.0-b53 "Thu Sep 22 02:00:28 EDT 2005" 16019 957900 0 0 1 0 3 5 3 37 jdk1.6.0-b54 "Thu Sep 29 01:54:34 EDT 2005" 16019 957900 0 0 0 0 3 6 3 38 jdk1.6.0-b55 "Thu Oct 06 01:54:14 EDT 2005" 16051 959014 0 0 0 0 3 6 3 39 jdk1.6.0-b56 "Thu Oct 13 01:54:12 EDT 2005" 16211 970835 0 0 0 0 3 6 3 40 jdk1.6.0-b57 "Thu Oct 20 01:55:26 EDT 2005" 16279 971627 0 0 0 0 3 6 3 41 jdk1.6.0-b58 "Thu Oct 27 01:56:30 EDT 2005" 16283 971945 0 0 0 0 3 6 3 42 jdk1.6.0-b59 "Thu Nov 03 01:56:58 EST 2005" 16232 972193 0 0 0 0 3 6 3 43 jdk1.6.0-b60 "Thu Nov 10 01:54:18 EST 2005" 16235 972346 0 0 0 0 3 6 3
次に示すコマンドを実行すると、db.xml 中間ファイルを生成することなく直接同じ情報を作成できます。
computeBugHistory jdk1.6.0-b*/jre/lib/rt.xml | filterBugs -bugPattern IL_ db.xml | mineBugHistory -formatDates
この情報を使って、 Sun JDK1.6.0 の各ビルドにおいて FindBugs によって発見された無限再起ループの数を表すグラフを表示します。青色の領域は、当該ビルドにおける無限再起ループの数を表しています。その上に描かれている赤色の領域は、以前のバージョンには存在したが当該バージョンでは除去された無限再起ループの数を表しています。 (したがって、赤色の領域と青色の領域を足し合わせた高さは決して減少しないことが保証されています。そして、新たに無限再起ループのバグが持ち込まれた時点で増加します) 。赤色の領域の高さは、当該バージョンにおいて修正または削除されたバグ数の合計で算出されます。バージョン 13 および 14 において見られる減少は、 FindBugs を使用して見つかった JDK のバグの報告を Sun が受け取ったことによるものです。
db.xml ファイルは、 jdk1.6.0 のすべてのビルドに対する検索結果を保持しています。したがって、次に示すコマンドを実行することで、優先度(高)または優先度(低)の正確性に関する警告の履歴が表示されます :
filterBugs -priority M -category C db.xml | mineBugHistory -formatDates
作成される表の例 :
seq version time classes NCSS added newCode fixed removed retained dead active 0 jdk1.6.0-b12 "Thu Nov 11 09:07:20 EST 2004" 13128 811569 0 1075 0 0 0 0 1075 1 jdk1.6.0-b13 "Thu Nov 18 06:02:06 EST 2004" 13128 811570 0 0 0 0 1075 0 1075 2 jdk1.6.0-b14 "Thu Dec 02 06:12:26 EST 2004" 13145 811786 3 0 6 0 1069 0 1072 3 jdk1.6.0-b15 "Thu Dec 09 06:07:04 EST 2004" 13174 811693 2 1 3 0 1069 6 1072 4 jdk1.6.0-b16 "Thu Dec 16 06:21:28 EST 2004" 13175 811715 0 0 1 0 1071 9 1071 5 jdk1.6.0-b17 "Thu Dec 23 06:27:22 EST 2004" 13176 811974 0 0 1 0 1070 10 1070 6 jdk1.6.0-b19 "Thu Jan 13 06:41:16 EST 2005" 13176 812011 0 0 0 0 1070 11 1070 7 jdk1.6.0-b21 "Thu Jan 27 05:57:52 EST 2005" 13177 812173 0 0 1 0 1069 11 1069 8 jdk1.6.0-b23 "Thu Feb 10 05:44:36 EST 2005" 13179 812188 0 0 0 0 1069 12 1069 9 jdk1.6.0-b26 "Thu Mar 03 06:04:02 EST 2005" 13199 811770 0 0 2 1 1066 12 1066 10 jdk1.6.0-b27 "Thu Mar 10 04:48:38 EST 2005" 13189 812440 1 0 1 1 1064 15 1065 11 jdk1.6.0-b28 "Thu Mar 17 02:54:22 EST 2005" 13185 812056 0 0 0 0 1065 17 1065 12 jdk1.6.0-b29 "Thu Mar 24 03:09:20 EST 2005" 13117 809468 3 0 8 26 1031 17 1034 13 jdk1.6.0-b30 "Thu Mar 31 02:53:32 EST 2005" 13118 809501 0 0 0 0 1034 51 1034 14 jdk1.6.0-b31 "Thu Apr 07 03:00:14 EDT 2005" 13117 809572 0 0 0 0 1034 51 1034 15 jdk1.6.0-b32 "Thu Apr 14 02:56:56 EDT 2005" 13169 811096 1 1 0 1 1033 51 1035 16 jdk1.6.0-b33 "Thu Apr 21 02:46:22 EDT 2005" 13187 811942 3 0 2 1 1032 52 1035 17 jdk1.6.0-b34 "Thu Apr 28 02:49:00 EDT 2005" 13195 813488 0 1 0 0 1035 55 1036 18 jdk1.6.0-b35 "Thu May 05 02:49:04 EDT 2005" 13457 829837 0 36 2 0 1034 55 1070 19 jdk1.6.0-b36 "Thu May 12 02:59:46 EDT 2005" 13462 831278 0 0 0 0 1070 57 1070 20 jdk1.6.0-b37 "Thu May 19 02:55:08 EDT 2005" 13464 831971 0 1 1 0 1069 57 1070 21 jdk1.6.0-b38 "Thu May 26 03:08:16 EDT 2005" 13564 836565 1 7 2 6 1062 58 1070 22 jdk1.6.0-b39 "Fri Jun 03 03:10:48 EDT 2005" 13856 849992 6 39 5 0 1065 66 1110 23 jdk1.6.0-b40 "Thu Jun 09 03:30:28 EDT 2005" 15972 959619 7 147 11 0 1099 71 1253 24 jdk1.6.0-b41 "Thu Jun 16 03:19:22 EDT 2005" 15972 959619 0 0 0 0 1253 82 1253 25 jdk1.6.0-b42 "Fri Jun 24 03:38:54 EDT 2005" 15966 958581 3 0 1 2 1250 82 1253 26 jdk1.6.0-b43 "Thu Jul 14 03:09:34 EDT 2005" 16041 960544 5 11 15 8 1230 85 1246 27 jdk1.6.0-b44 "Thu Jul 21 03:05:54 EDT 2005" 16041 960547 0 0 0 0 1246 108 1246 28 jdk1.6.0-b45 "Thu Jul 28 03:26:10 EDT 2005" 16037 960606 19 0 2 0 1244 108 1263 29 jdk1.6.0-b46 "Thu Aug 04 03:02:48 EDT 2005" 15936 951355 13 1 1 32 1230 110 1244 30 jdk1.6.0-b47 "Thu Aug 11 03:18:56 EDT 2005" 15964 952387 163 8 7 20 1217 143 1388 31 jdk1.6.0-b48 "Thu Aug 18 08:10:40 EDT 2005" 15970 953421 0 0 0 0 1388 170 1388 32 jdk1.6.0-b49 "Thu Aug 25 03:24:38 EDT 2005" 16048 958940 1 11 1 0 1387 170 1399 33 jdk1.6.0-b50 "Thu Sep 01 01:52:40 EDT 2005" 16287 974937 19 27 16 7 1376 171 1422 34 jdk1.6.0-b51 "Thu Sep 08 01:55:36 EDT 2005" 16362 979377 1 15 3 0 1419 194 1435 35 jdk1.6.0-b52 "Thu Sep 15 02:04:08 EDT 2005" 16477 979399 0 0 1 1 1433 197 1433 36 jdk1.6.0-b53 "Thu Sep 22 02:00:28 EDT 2005" 16019 957900 13 12 16 20 1397 199 1422 37 jdk1.6.0-b54 "Thu Sep 29 01:54:34 EDT 2005" 16019 957900 0 0 0 0 1422 235 1422 38 jdk1.6.0-b55 "Thu Oct 06 01:54:14 EDT 2005" 16051 959014 1 4 7 0 1415 235 1420 39 jdk1.6.0-b56 "Thu Oct 13 01:54:12 EDT 2005" 16211 970835 6 8 37 0 1383 242 1397 40 jdk1.6.0-b57 "Thu Oct 20 01:55:26 EDT 2005" 16279 971627 0 0 0 0 1397 279 1397 41 jdk1.6.0-b58 "Thu Oct 27 01:56:30 EDT 2005" 16283 971945 0 1 1 0 1396 279 1397 42 jdk1.6.0-b59 "Thu Nov 03 01:56:58 EST 2005" 16232 972193 6 0 5 0 1392 280 1398 43 jdk1.6.0-b60 "Thu Nov 10 01:54:18 EST 2005" 16235 972346 0 0 0 0 1398 285 1398 44 jdk1.6.0-b61 "Thu Nov 17 01:58:42 EST 2005" 16202 971134 2 0 4 0 1394 285 1396
findbugs の実行とその後のデータ・マイニングツールの活用の両方を実行している ant スクリプトの完全な例を以下に示します :
<project name="analyze_asm_util" default="findbugs"> <!-- findbugs タスク定義 --> <property name="findbugs.home" value="/Users/ben/Documents/workspace/findbugs/findbugs" /> <property name="jvmargs" value="-server -Xss1m -Xmx800m -Duser.language=en -Duser.region=EN -Dfindbugs.home=${findbugs.home}" /> <path id="findbugs.lib"> <fileset dir="${findbugs.home}/lib"> <include name="findbugs-ant.jar"/> </fileset> </path> <taskdef name="findbugs" classname="edu.umd.cs.findbugs.anttask.FindBugsTask"> <classpath refid="findbugs.lib" /> </taskdef> <taskdef name="computeBugHistory" classname="edu.umd.cs.findbugs.anttask.ComputeBugHistoryTask"> <classpath refid="findbugs.lib" /> </taskdef> <taskdef name="setBugDatabaseInfo" classname="edu.umd.cs.findbugs.anttask.SetBugDatabaseInfoTask"> <classpath refid="findbugs.lib" /> </taskdef> <taskdef name="mineBugHistory" classname="edu.umd.cs.findbugs.anttask.MineBugHistoryTask"> <classpath refid="findbugs.lib" /> </taskdef> <!-- findbugs タスク定義 --> <target name="findbugs"> <antcall target="analyze" /> <antcall target="mine" /> </target> <!-- 分析を行うタスク--> <target name="analyze"> <!-- asm-util に対して findbugs を実行する --> <findbugs home="${findbugs.home}" output="xml:withMessages" timeout="90000000" reportLevel="experimental" workHard="true" effort="max" adjustExperimental="true" jvmargs="${jvmargs}" failOnError="true" outputFile="out.xml" projectName="Findbugs" debug="false"> <class location="asm-util-3.0.jar" /> </findbugs> </target> <target name="mine"> <!-- 最新の分析結果に情報を設定する --> <setBugDatabaseInfo home="${findbugs.home}" withMessages="true" name="asm-util-3.0.jar" input="out.xml" output="out-rel.xml"/> <!-- 履歴ファイル (out-hist.xml) が既に存在するかどうかを確認する --> <condition property="mining.historyfile.available"> <available file="out-hist.xml"/> </condition> <condition property="mining.historyfile.notavailable"> <not> <available file="out-hist.xml"/> </not> </condition> <!-- このターゲットは、履歴ファイルが存在しないとき (初回) だけ実行されます --> <antcall target="history-init"> <param name="data.file" value="out-rel.xml" /> <param name="hist.file" value="out-hist.xml" /> </antcall> <!-- 上記以外の場合に実行されます --> <antcall target="history"> <param name="data.file" value="out-rel.xml" /> <param name="hist.file" value="out-hist.xml" /> <param name="hist.summary.file" value="out-hist.txt" /> </antcall> </target> <!-- 履歴ファイルを初期化します --> <target name="history-init" if="mining.historyfile.notavailable"> <copy file="${data.file}" tofile="${hist.file}" /> </target> <!-- バグ履歴を算出します --> <target name="history" if="mining.historyfile.available"> <!-- ${data.file} を ${hist.file} にマージします --> <computeBugHistory home="${findbugs.home}" withMessages="true" output="${hist.file}"> <dataFile name="${hist.file}"/> <dataFile name="${data.file}"/> </computeBugHistory> <!-- 履歴を算出して ${hist.summary.file} に出力します --> <mineBugHistory home="${findbugs.home}" formatDates="true" noTabs="true" input="${hist.file}" output="${hist.summary.file}"/> </target> </project>