You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 13 Next »

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.

Use of the try-with-resources statement is also illustrated in ERR05-J. Do not let checked exceptions escape from a finally block, FIO03-J. Remove temporary files before termination, and FIO04-J. Release resources when they are no longer needed.

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.

public void processFile(String inPath, String outPath) throws IOException{
  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 {
    try {
      if (br != null) {
       	br.close();
      }
      if (bw != null) {
       	bw.close();
      }
    } catch (IOException x) {
      // handle error
    }
  }
}

Compliant Solution (finally block)

This compliant solution uses a second finally block to guarantee that bw is properly closed even if an exception is thrown while closing br.

public void processFile(String inPath, String outPath) throws IOException {
  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) {
      try {
        br.close();
      } catch (IOException x) {
        // handle error
      } finally {
        if (bw != null) {
          try {
            bw.close();
          } catch (IOException x) {
            // handle error
          }
        }
      }
    }
  }
}

Compliant Solution (try-with-resources)

This compliant solution uses a try-with-resources statement to manage both br and bw.  It will preserve any exceptions thrown during the processing of the input while still guaranteeing that both br and bw are properly closed, regardless of what exceptions occur. Finally, this code demonstrates how to access every exception that may be produced from the try-with-resources block.

public void processFile(String inPath, String outPath) throws IOException{
  try (BufferedReader br = new BufferedReader(new FileReader(inPath));
       BufferedWriter bw = new BufferedWriter(new FileWriter(outPath));) {
    // 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 files, the exception will be printed by the "thrown exception: " statement. If an exception is thrown during processing, and another one is thrown while trying to close either 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.

Bibliography

  • No labels