フロー解析エンジンは、解析されたコードからパスを分析し、さまざまな問題を検出します。アプリケーション全体にわたって「実行される可能性があるパス」をすべて解析するのは現実的ではない場合もあるため、解析レベルの深さを設定できます。解析レベルが深いほど、発見される違反の数が増えます。ただし、パフォーマンスが低下し、若干メモリの消費量が増加します。
解析の深さは、DTP でテスト コンフィギュレーション インターフェイスを使用して設定します。Report Center > [テスト コンフィギュレーション] > [静的解析] > [フロー解析詳細設定] > [パフォーマンス] > [解析の深さ] にアクセスし、以下のいずれかのオプションを選択します。
デフォルトの解析レベルの深さは [標準] です。
解析レベルの深さの他に、フロー解析エンジンはタイムアウト設定を利用して、妥当な時間内で解析が終了するようにします。タイムアウトの設定を行うには、DTP でテスト コンフィギュレーション インターフェイスを使用します。Report Center > [テスト コンフィギュレーション] > [静的解析] > [フロー解析詳細設定] > [パフォーマンス] > [タイムアウトの方針] にアクセスし、以下のいずれかのオプションを選択します。
デフォルトのタイムアウト オプションは [時間] であり、タイムアウト秒数は 60 秒です。解析中に発生したフロー解析タイムアウトについての情報を得るには、解析後に生成されるレポートで [セットアップの問題] セクションを確認してください。
スワップ モードでは、解析データをハードディスクに書き込みます。解析データのスワップは、インクリメンタル解析と同じ永続性記憶装置を使用し、インクリメンタル解析と似たプロセスで実行されます。大きなプロジェクトで解析を実行する場合、解析するソース コードの意味論的モデルを表す解析データが、フロー解析が使用できるすべてのメモリを消費する可能性があります。この現象が発生した場合、フロー解析は現在必要ない解析データをメモリから削除し、後でディスクから再び読み込みます。
一般的に、 Xmx JVM オプションを使って JVM ヒープのサイズを大きくしてJtestを実行することを推奨します。これはスワップを最小限にするためであり、結果としてパフォーマンスが向上します。充分なメモリがある場合、解析データのスワップは無効化しても構いません。スワップを無効化すると、コード解析の速度が上がる場合があります。
スワップ モードを有効化/無効化するには、DTP のテスト コンフィギュレーション画面を使用します。
ディスクへの解析データのスワップを有効化:デフォルトで有効です。大量のメモリを必要としない小さなサイズのプロジェクトに対してフロー解析を実行する場合、または 64-bit システムのように十分なメモリがある場合、このオプションを無効化すると、解析のパフォーマンスが向上する場合があります。
DTP のテスト コンフィギュレーション画面では、次のオプションを設定できます。
[null チェック メソッド] オプションを指定すると、メソッドに null パラメーターが渡されたときに返す期待値を指定できます。そのため、偽陽性が減少するほか、null 変数の値が不明なときに通常作成される過剰なパスが減少します。
[有効 ] チェックボックスをオンにして、以下の情報を指定します。
フロー解析は解析スコープでメソッドを解析します。たとえばサード パーティのライブラリなど、現在の解析スコープの外にメソッドがある場合、null チェック メソッドでパラメーターを指定する必要があります。この例のクラスは、異なるアセンブリに定義されており、解析スコープ (UString
) の外ります。このクラスには、Java の文字列があるコードをさまざまな方法で操作するための static メソッドがあります。その 1 つが UString.isEmptyOrNull(String)
であり、これは以下のように定義されます。
public class UString { static boolean isEmptyOrNull(String variable) { if ((variable == null) || (variable.length() == 0)) { return true; } return false; } } |
そして、フロー解析の ルール BD-EXCEPT-NP ルールによって解析される次のクラスがあります。
public class SomeClass { void someMethod(String variable) { boolean flag = variable == null; // violation search starts here if (UString.isEmptyOrNull(variable)) { /** * In case variable is null, we will always get to this branch of the if clause. */ System.out.println("String is empty"); } else { variable.toString(); // FALSE POSITIVE BD-EXCEPT-NP VIOLATION } } } |
フロー解析は メソッド isEmptyOrNull()
の戻り値が不明であると仮定します。その理由は、このメソッドは解析スコープ中にないからです。フロー解析は if
文の then
および else
ブランチを解析し、それらの文の 1 つで違反を発見します。しかし、変数が null の場合、このメソッド呼び出しは true を返します。 null チェック メソッドのメソッド リストに UString.isEmptyOrNull()
を追加して戻り値を指定することで、追跡された変数がこのメソッドに渡されたときにフロー解析は違反をレポートしなくなります。なぜなら、if
文の誤ったブランチが解析されず、その結果として偽陽性が回避されるからです。
null チェック メソッドのパラメーターに追加されるメソッドは、単純な Boolean 型の戻り値を持つ、static メソッドであるべきです。 この制限事項は、パラメーター指定が複雑になり過ぎることを防ぎ、null チェック メソッドの結果に影響しかねない変数が他にないことを保証します。
[リソース] タブでは、BD.RES (リソース) カテゴリのルールを使ってチェックするリソースを定義することができます。BD.RES カテゴリのルールは、[リソース] タブで定義および有効化されているすべてのリソースについて、リソースが正しく使用されているかをチェックします。
[リソース アロケーター] テーブルには、リソースを生成するメソッドの記述を入力できます。テーブルには以下の列があります。
一般的に、アロケーター メソッドはエラー コードを返してリソース割り当ての失敗を表します。アロケーター メソッド はリソースへのポインターを返し、通常 NULL ポインターはリソース割り当ての失敗を表します。リソース リークを探すときに、フロー解析はリソースの割り当てが成功したか失敗したかを把握できる必要があります。これは、割り当てが実際に発生したパス上で発見されないクローザー メソッドへの呼び出しだけをフロー解析がレポートするのに役立ちます。リソース アロケーター関数がリソースへのポインターを返し、このポインターが NULL でない場合、フロー解析はリソースが正常に割り当てられたと推測します。
[リソース クローザー] テーブルには、リソースをクローズするメソッドの記述を入力できます。テーブルには以下の列があります。