其他分享
首页 > 其他分享> > Tomcat连接池:几种不释放连接的方法

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