We have discovered a rather very nasty leak in JBoss 6.1's JDBC pool.
This is caused by code relying on the close
method on the connection to close underlying statements.
Although the WrappedConnection does close them, the code looks like this:
if (statements != null) {
for (Iterator
<Map.Entry<WrappedStatement, Throwable>> i=statements.entrySet().iterator();
i.hasNext(); )
{
Map.Entry<WrappedStatement, Throwable> entry = i.next();
WrappedStatement ws= entry.getKey();
if (trackStatements==BaseWrapperManagedConnectionFactory.TRACK_STATEMENTS_TRUE_INT)
{
Throwable stackTrace = entry.getValue();
log.warn("Closing a statement you left open, please do your own housekeeping",
stackTrace);
}
try
{
ws.internalClose();
}
catch (Throwable t)
{
log.warn("Exception trying to close statement:", t);
}
}
}
The statements object never removes the statements from its map, and the map grows, and grows, and those statements hold result sets, etc. (at least in the JDBC driver I'm using).
I'm wondering if anyone ever replaced the jdbc pool in JBoss with an alternative implementation that is more robust than this?
As a small addendum to this, the code and behavior is the same with result sets (essentially copy and paste), although the memory leak may not be significant if you don't hold on to the statement for any length of time (unlike the connection which lives in the pool by design).
JBoss deploys its connection pooling for datasource as a resource adapter RAR. By default, there are two available jboss-local-jdbc.rar
and jboss-xa-jdbc.rar
in deploy
folder. Connection factory and wrapper to use are declared in META-INF/ra.xml
So the option is to replace one or both of these resource adapters according to your declared datasource. But the implementation has to support resource enlistment into transaction with JTS and also security checks.
Not a so easy job and you will probably be the first guy to do it.