finallyブロックの中では、return, break, continue, throw文を決して使用してはならない。プログラムの実行が finallyブロックを持つ tryブロックに入ると、try ブロック(や対応するcatchブロック)の処理が完了するかしないかに関わらず、finallyブロックは必ず実行される。finally ブロックの処理を途中で終了させる文は、try ブロックの処理も中断させてしまう。そのため、tryブロックやcatchブロックからスローされる例外を抑制してしまう。[JLS 2005]
違反コード
以下の違反コードでは、return文が存在するため、finallyブロックの処理が途中で終了してしまう。
class TryFinally {
private static boolean doLogic() {
try {
throw new IllegalStateException();
} finally {
System.out.println("logic done");
return true;
}
}
}
return文によってfinallyブロックの処理が終了しているため、IllegalStateException例外の発生が抑制されている。
適合コード
以下の解決法では、finally ブロックから return 文を取り除いている。
class TryFinally {
private static boolean doLogic() {
try {
throw new IllegalStateException();
} finally {
System.out.println("logic done");
}
// return 文はここに書くこと。ただし、条件に応じて例外がスローされる
// 場合のみ。
}
}
例外
ERR04-EX0: finallyブロック内で完結する制御フロー文を書くことは構わない。
たとえば、以下のコードはこのルールの違反には当たらない。break文はwhileループを終了させはするが、finallyブロックは終了させていないからである。
class TryFinally {
private static boolean doLogic() {
try {
throw new IllegalStateException();
} finally {
int c;
try {
while ((c = input.read()) != -1) {
if (c > 128) {
break;
}
}
} catch (IOException x) {
// ハンドラへ処理を移す
}
System.out.println("logic done");
}
// return 文はここに書くこと。ただし、条件に応じて例外がスローされる場合のみ。
}
}
リスク評価
finallyブロックの処理を途中で終了すると、tryブロックやcatchブロックの外にスローされるべき例外がスローされなくなってしまう。
| ルール | 深刻度 | 可能性 | 修正コスト | 可能性 | レベル |
|---|---|---|---|---|---|
| ERR04-J | 低 | 中 | 中 | P4 | L3 |
関連ガイドライン
| MITRE CWE | CWE-459. Incomplete cleanup |
| CWE-584. Return inside finally block |
参考文献
| [Bloch 2005] | Puzzle 36. Indecision |
| [Chess 2007] | 8.2, Managing Exceptions, The Vanishing Exception |
| [JLS 2005] | §14.20.2, Execution of try-catch-finally |
翻訳元
これは以下のページを翻訳したものです。
ERR04-J. Do not exit abruptly from a finally block (revision 82)



