Never use {{ Wiki Markup return
}}, {{break
}}, {{continue
}}, or {{throw
}} statements within a {{finally
}} block. When program execution enters a {{try
}} block that has a {{finally
}} block, the {{finally
}} block always executes , regardless of whether the {{try
}} block (or any associated {{catch
}} blocks) executes to normal completion. Statements that cause the {{finally
}} block to complete abruptly also cause the {{try
}} block to complete abruptly and consequently suppress any exception thrown from the {{try
}} or {{catch
}} blocks. According to the _The Java Language Specification_, [§14, §14.20.2, "Execution of try-finally
and try-catch-finally
|http://java.sun.com/docs/books/jls/third_edition/html/statements.html#14.20.2] \[[JLS 2005|AA. References#JLS 05]\]" [JLS 2015]:
If execution of the
try
block completes abruptly for any other reasonR
, then thefinally
block is executed. Then there is a choice:
- If the
finally
block completes normally, then thetry
statement completes abruptly for reasonR
.- If the
finally
block completes abruptly for reasonS
, then thetry
statement completes abruptly for reasonS
(and reasonR
is discarded).
Noncompliant Code Example
In this noncompliant code example, the finally
block completes abruptly because of a return
statement in the block.:
Code Block | ||
---|---|---|
| ||
class TryFinally {
private static boolean doLogic() {
try {
throw new IllegalStateException();
} finally {
System.out.println("logic done");
return true;
}
}
}
|
...
This compliant solution removes the return
statement from the finally
block.:
Code Block | ||
---|---|---|
| ||
class TryFinally {
private static boolean doLogic() {
try {
throw new IllegalStateException();
} finally {
System.out.println("logic done");
}
// Any return statements must go here;
// applicable only when exception is thrown conditionally
}
}
|
Exceptions
ERRO4-J-EX0: Control flow statements whose destination is within the finally
block are perfectly acceptable. For example, the following code does not violate this rule , because the break
statement exits within the while
loop , but not within the finally
block.:
Code Block | ||
---|---|---|
| ||
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) { // forwardForward to handler } System.out.println("logic done"); } // Any return statements must go here; applicable only when exception is thrown conditionally } } |
...
Abrupt completion of a finally
block masks any exceptions thrown inside the associated try
and catch
blocks.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
ERR04-J |
Low |
Probable |
Medium | P4 | L3 |
Automated Detection
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
Coverity | 7.5 | PW.ABNORMAL_TERMINATION_ OF_FINALLY_BLOCK | Implemented | ||||||
Parasoft Jtest |
| CERT.ERR04.ARCF CERT.ERR04.ATSF | Avoid using 'return's inside 'finally blocks if thare are other 'return's inside the try-catch block Do not exit "finally" blocks abruptly | ||||||
PVS-Studio |
| V6051 | |||||||
SonarQube |
| S1143 | Jump statements should not occur in "finally" blocks |
Related Guidelines
Bibliography
Block |
Bibliography
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="de01b966-605a-4e94-bb6f-fcec661f8186"><ac:plain-text-body><![CDATA[
[[Bloch 2005
Puzzle 36. Indecision |
]]></ac:plain-text-body></ac:structured-macro>
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="fb4b487e-83b1-451f-9e77-9072933d8a3e"><ac:plain-text-body><![CDATA[
] |
Section 8.2, "Managing Exceptions, The Vanishing Exception |
]]></ac:plain-text-body></ac:structured-macro>
" |
AA. References#JLS 05]]
[ |
http://java.sun.com/docs/books/jls/third_edition/html/statements.html#14.20.2]
]]></ac:plain-text-body></ac:structured-macro>
...