Bug #29797 Statement objects not being closed when garbage collected / memory leak
Submitted: 13 Jul 2007 20:45 Modified: 14 Jul 2007 2:56
Reporter: Jordan Schidlowsky Email Updates:
Status: Won't fix Impact on me:
None 
Category:Connector / J Severity:S3 (Non-critical)
Version:5.1 OS:Linux
Assigned to: CPU Architecture:Any
Tags: close, memory leak, ResultSet, statement

[13 Jul 2007 20:45] Jordan Schidlowsky
Description:
Per the Java API:

A Statement object is automatically closed when it is garbage collected. When a Statement object is closed, its current ResultSet object, if one exists, is also closed.

I have found that not explicitly closing statement objects causes resources to not be freed when the statement is no longer referenced and GC'd.  Explicitly closing the statement solves this problem.  

How to repeat:
while(true) {
   Statement s = conn.createStatement();
   s.executeQuery(someQuery);
   RestultSet rs = s.getResultSet();

   rs.close();
   // NOTE: not closing s before end of loop
   // i.e. s should be GC'd and closed
}

Suggested fix:
 Some fix in driver.
[14 Jul 2007 2:56] Mark Matthews
This "auto cleanup" requirement is actually removed in JDBC-4.0 because it's unworkable. GC is _not_ deterministic (can't count on when it happens, can't count on it being single-threaded, can't count on it happening _at_all_), which is contrary to orderly closing of database statements which often require synchronized access to the backend database over the network to clean things up.

Also, the very fact that you add a finalize() method to a class limits throughput of the application during GC by up to 15% (in our measurements we found at least a 10% performance reduction just by having a void finalize() method on Statement because of the various internal class instances that the VM creates and has to synchronize on to handle this functionality).

For these reasons we're not fixing this, and advise you to explicitly clean up your statement instances by closing() them, as it's just good practice anyway, and JDBC-4.0 will force you to do the same thing eventually.