You might not like that code, but in this situation it is necessary. (Though you can wrap the code in a method like @fge's closeQuietly
method.)
But there is a more fundamental problem. Changing someWork
to close the connection in a finally
block is not sufficient to prevent a leak ... in this situation!!
Why?
Consider this:
SomeClass sc = new SomeClass(createConnection());
// do some stuff
sc.someWork();
Q1: What happens if an exception is thrown in the "do some stuff" code?
Q2: What happens if an exception is thrown while creating / constructing the SomeClass
? (Note: this is possible even with the simplest of constructors. For example, an OOME could be thrown by the new
operation ...)
Answer: the Connection object is leaked ... in both bases!
The fix is to allocate the resource (e.g. the Connection object) within, or immediately before the try / catch / finally; e.g.
Connection c = createConnection();
try {
// do something
} catch (SomeException e) {
// some exception code
} finally {
if (c != null){
try {c.close();} catch (SomeException e) {}
}
}
In Java 7 you can also write it like this:
try (Connection c = createConnection()) {
// do something
} catch (SomeException e) {
// some exception code
}
provided that Connection
implements the AutoCloseable
interface. The Java 7 version is "syntactic sugar" for a more complicated implementation that takes care of checking for null
, calling close()
and dealing with any resulting exceptions intelligently. (The JLS gives the details of what "try with resource" actually does.)
For the record:
The issue is not garbage collection / collecting. The issue is that the Connection
object needs to be closed.
Assigning null
won't cause an object to be closed. It won't even cause it to be garbage collected. At best, it can make the object eligible for garbage collection ... in some future GC run.
Catching Exception
is a really bad idea. Read this: Need authoritative source for why you shouldn't throw or catch java.lang.Exception