JDK 1.7 introduced the "try-with-resources" statement [JLS 2011] §14.20.3, "try-with-resources" that makes it much easier to deal with resources that implement the java.lang.AutoCloseable
interface, including those that implement the java.io.Closeable
interface.
Using the try-with-resources statement avoids problems that can arise when closing resources with an ordinary try-catch-finally block, such as failing to close a resource because an exception is thrown as a result of closing another resource, or masking an important exception when a resource is closed.
Noncompliant Code Example
This noncompliant code example uses an ordinary try-finally block to try to close two resources. However, if closing the Bufferedreader
br
results in an exception being thrown, then the BufferedWriter
bw
will not be closed.
String inPath = ...; // input file path String outPath = ...; // output file path BufferedReader br = null; BufferedWriter bw = null; try { br = new BufferedReader(new FileReader(inPath)); bw = new BufferedWriter(new FileWriter(outPath)); // process the input and produce the output } finally { if (br != null) { br.close(); } if (bw != null) { bw.close(); } }
Compliant Solution
This compliant solution uses a try-with-resources statement which will guarantee that both br
and bw
are closed, regardless of any exceptions potentially thrown during the close operations.
String inPath = ...; // input file path String outPath = ...; // output file path try ( BufferedReader br = new BufferedReader(new FileReader(inPath)); BufferedWriter bw = new BufferedWriter(new FileWriter(outPath)); ) { // process the input and produce the output }
Noncompliant Code Example
This noncompliant code example uses an ordinary try-finally block to try to close a resource. However, if there is an exception thrown during the processing of the input and another exception thrown when closing the Bufferedreader
br
, then the exception thrown as a result of processing the input will be lost, and important information about that exceptional circumstance may be missed.
String inPath = ...; // input file path BufferedReader br = null; try { br = new BufferedReader(new FileReader(inPath)); // process the input and produce the output } finally { if (br != null) { br.close(); } }
Compliant Solution
This compliant solution uses a try-with-resources statement which will not suppress any exceptions thrown during the processing of the input while still guaranteeing that br
is closed.
String inPath = ...; // input file path try ( BufferedReader br = new BufferedReader(new FileReader(inPath)); ) { // process the input and produce the output } catch (IOException ex) { System.err.println("thrown exception: " + ex.toString()); Throwable[] suppressed = ex.getSuppressed(); for (int i = 0; i < suppressed.length; i++) { System.err.println("suppressed exception: " + suppressed[i].toString()); } }
If only one exception is thrown, either during opening, processing, or closing of the file, it will be printed by the "thrown exception: "
statement. If an exception is thrown during processing, and another one is thrown while trying to close the file, then the "thrown exception: "
statement will print the exception encountered while closing the file, and the "suppressed exception: "
statement will print the exception encountered during processing.
Applicability
Failing to use a try-with-resources statement when dealing with closeable resources may result in some resources not being closed, or important exceptions being masked, possibly resulting in a denial of service attack.