Java Try/Catch/Finally Best Practices While Acquiring/Closing Resources

Java try/catch/finally best practices while acquiring/closing resources

Note that the following is only applicable for Java 6 and earlier. For Java 7 and later, you should switch to using try-with-resources ... as described in other answers.

If you are trying to catch and report all exceptions at source (in Java 6 or earlier), a better solution is this:

ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(new FileOutputStream(file));
oos.writeObject(shapes);
oos.flush();
} catch (FileNotFoundException ex) {
// complain to user
} catch (IOException ex) {
// notify user
} finally {
if (oos != null) {
try {
oos.close();
} catch (IOException ex) {
// ignore ... any significant errors should already have been
// reported via an IOException from the final flush.
}
}
}

Notes:

  • The standard Java wrapper streams, readers and writers all propagate close and flush to their wrapped streams, etc. So you only need to close or flush the outermost wrapper.
  • The purpose of flushing explicitly at the end of the try block is so that the (real) handler for IOException gets to see any write failures1.
  • When you do a close or flush on an output stream, there is a "once in a blue moon" chance that an exception will be thrown due to disc errors or file system full. You should not squash this exception!.

If you often have to "close a possibly null stream ignoring IOExceptions", then you could write yourself a helper method like this:

public void closeQuietly(Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (IOException ex) {
// ignore
}
}
}

then you can replace the previous finally block with:

} finally {
closeQuietly(oos);
}

Another answer points out that a closeQuietly method is already available in an Apache Commons library ... if you don't mind adding a dependency to your project for a 10 line method.

But be careful that you only use closeQuietly on streams where IO exceptions really are irrelevant.

UPDATE : closeQuietly is deprecated in version 2.6 of the Apache Commons API. Java 7+ try-with-resources makes it redundant.


On the issue of flush() versus close() that people were asking about in comments:

  • The standard "filter" and "buffered" output streams and writers have an API contract that states that close() causes all buffered output to be flushed. You should find that all other (standard) output classes that do output buffering will behave the same way. So, for a standard class it is redundant to call flush() immediately before close().

  • For custom and 3rd-party classes, you need to investigate (e.g. read the javadoc, look at the code), but any close() method that doesn't flush buffered data is arguably broken.

  • Finally, there is the issue of what flush() actually does. What the javadoc says is this (for OutputStream ...)

    If the intended destination of this stream is an abstraction provided by the underlying operating system, for example a file, then flushing the stream guarantees only that bytes previously written to the stream are passed to the operating system for writing; it does not guarantee that they are actually written to a physical device such as a disk drive.

    So ... if you hope / imagine that calling flush() guarantees that your data will persist, you are wrong! (If you need to do that kind of thing, look at the FileChannel.force method ...)

Can we avoid finally block if we do resource cleanup in both try and catch together?

Use try-with-resources wherever possible or try-finally (try-catch-finally).

Can we avoid finally block if we do resource cleanup in both try and catch together?

Why? You could, by substituting a well working and for this purpose designed java idiom by errorneous code and by using some antipatterns.

Assuming, your are going to log or handle exceptions in real life, this is why your code is not the same:

Not working:

  • your connection is not always closed, since you are only handling exceptions, no errors or throwables

Some antipatterns:

  • You are re-inventing the wheel
  • DRY (don't repeat yourself)
  • Catch the most specific exceptions first; avoid handling Exception, Error or Throwable in general
  • be aware of swallowing exceptions (possible with finally, too!), try-with-resources is using suppressed exceptions for this
  • ...

How to deal with an exception thrown by file close?

Is it acceptable to just ignore when a stream close throws exception?

In most cases it is, but it really depends on the context. If you decide not to handle the close exception and are looking to avoid extra try-catch block, then you can use IOUtils from commons-io library.

finally {
IOUtils.closeQuietly(pdf);
}

This is equivalent to the following

finally {
try {
if (closeable != null) {
closeable.close();
}
} catch (IOException ioe) {
// ignore
}
}

Java Serialization: close streams in try or in a finally block?

You should close in finally block.

It's a bad habit to close in try block.

  try { 
e = (Employee) in.readObject(); //Possibility of exception
} catch(IOException i) {

} catch(ClassNotFoundException c) {

} finally {
in.close();
fileIn.close();
}

When someone is writing a code by knowing it will throw an exception,he/she has to close the opened resources

Dealing with code duplication of acquiring resources in try...finally blocks

You can use aspects. The great example of aspects in work is the Spring framework. One of the features that is realized in that way is the transaction support. The transactional aspects are handling the transaction opening , committing (on normal proceed) or rollbacking (on exception), and releasing in each case.

Benefits of the finally clause in exception handling

Whatever StinePike has written is perfect but I want to add something in that.

Finally block is executed either exception occurs or not.... so we can achieve this without finally block by writing the finally block code in try block and also in catch block(). Now if exception doesn't occur, it execute the code from try block.If exception occurs, it execute the code from catch block.

So the additional advantage from the finally block is that you can write return statement anywhere in the method, still finally block is executed but the code is not executed if you don't write the code in finally block and return from the method(on the basis of some condition) before reaching to that code.

Is Try-Catch More or Less Expensive Than Try-With-Resources

  1. try-catch is not the expensive part. Throwing the exception is (generating the stacktrace).
  2. "Expensive" above means "costs some microseconds".
  3. try-with-resources is just try-catch with proper code needed to reliably close the resource.
  4. Your measurement code cannot prove anything due to all the well-known pitfalls of trying to measure performance within an optimizing runtime such as HotSpot. You need to warm up, repeat the same many times, and much more.
  5. If your result is above 10 ms, then clearly you cannot have an issue with try-catch, which can altogether impose an overhead of several microseconds.

Close a resource in a Finally block from a try catch with resources

Client will be closed, cause you are using try-with-resources (when you open resourse in try(resource definition)), which closes resource after try block automatically, you don`t need to write finally block.

Is finally block really reliable to close the resource? Updated with code snippet

I was wondering whether finally block is really reliable to close the resource or not; such as, database connection?

It depends on what you mean by "reliable".

  • It may not execute if the JVM is aborted hard (e.g. due to a bug in the JIT)
  • It may not execute if the JVM is in the process of terminating normally (see Harmeet's answer)
  • It won't execute it the contents of the try block hangs forever
  • It won't execute if the computer suddenly loses power

In all of these cases I'd expect the database to notice that the other end of the connection had gone away anyway.

If your architect has a specific scenario in mind where they believe the finally block won't execute, he should provide an example of that scenario, at which point you'll almost certainly be able to prove them wrong. If they refuse to give any specifics, then ignore them, and suggest to management that they should start looking for a less superstitious architect.

In this scenario, I am skeptical about finally block because according to the test, finally block is not releasing the resource instead the web app is acquiring more connection. At end, Tomcat 5.5 is hanged every two/three hours later.

Sounds like the test is probably invalid, or you're leaking connections elsewhere, or you're not closing the connection. It's easy to validate though: put logging in the finally block, to validate that the code you expect to release the resource is at least being called. If it's being called but not releasing the connection, then it's no longer an issue around finally blocks.



Related Topics



Leave a reply



Submit