Tomcat连接池:几种不释放连接的方法
作者:互联网
我正在使用tomcat连接池.但是我在跟踪异常
org.apache.tomcat.dbcp.dbcp.SQLNestedException:无法获得连接,池错误超时等待空闲对象
所以我在context.xml中放入以下行以查找泄漏:
removeAbandoned =“ true” logAbandoned =“ true” removeAbandonedTimeout =“ 3”
然后我开始获取以下异常org.apache.tomcat.dbcp.dbcp.AbandonedTrace $AbandonedObjectException:从未关闭通过以下代码创建的DBCP对象2015-01-17 22:12:18:
因此,我发现了导致这种泄漏的两种罪魁祸首方法.两种方法都有获得连接的通用方法,即调用unwrap获得对驱动程序特定连接的访问权限.
try (Connection conn = DataSourceConnectionPool.getConnection().unwrap(OracleConnection.class);
OracleCallableStatement cstmt = (OracleCallableStatement) conn.prepareCall(MIGRATE_ACCOUNT)) {
...
....
)
需要注意的重要一点是,我正在使用JDK7中的try块,即自动资源管理,因此我不需要finally块.连接关闭由JDK自动处理.但是为什么这个展开的连接没有关闭.当我尝试执行以下操作时:
try (Connection poolConn = DataSourceConnectionPool.getConnection();
Connection conn = poolConn.unwrap(OracleConnection.class);
我正在获取java.sql.SQLException:已经关闭.那么如何关闭此连接.我是否必须手动执行而不使用try块?不应该尝试阻止句柄来处理吗?
解决方法:
这是对连接池的不正确使用.绝对不要在未包装的连接上调用close().
使用池连接的正常流程是
>获取连接,池将获得物理连接,并将其包装在自己的包装器中返回
>您使用连接
>您可以在Connection上调用close().这实际上并没有关闭任何内容,池的包装程序拦截了close()调用,只是将(仍处于活动状态的)连接返回给池.
之所以可行,是因为该池具有包装器类,例如实现Connection的PoolableConnection. PoolableConnection委托底层连接进行实际工作,但它(除其他事项外)以不同的方式实现close().这将破坏当前的PoolableConnection包装器,并将底层的Connection返回到连接池.例如.
这样,您的程序逻辑可以从数据源获取连接,使用Connection,然后使用close(),就像正常的非池化Connection一样.
正是这种透明性使连接池易于使用.
现在,当您调用unwrap时,PooledConnection使您可以访问其内部的,真实的Connection委托.
您要做的就是在委托上调用close()!
这有两个效果:
>它不会在PooledConnection上调用close(),因此Connection不会返回到池中.
>它关闭了池下的底层连接.这不应该成为问题,因为池本身将处理掉线的连接.
因此,您需要非常小心.始终在从池中获得的Connection上调用close(),以将其返回到池中.永远不要在基础连接上调用close().
因此,您的代码应为:
try (final Connection poolConn = DataSourceConnectionPool.getConnection()) {
final Connection conn = poolConn.unwrap(OracleConnection.class);
//do stuff with conn
//do not close conn!!
}
//poolConn is returned to the pool
标签:java,jdbc,tomcat,connection-pooling 来源: https://codeday.me/bug/20191011/1896581.html