You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JBoss中数据库连接泄漏疑问:未关闭连接为何返回连接池?

问题背景

我的Java Spring Boot只读应用(无写入操作)中,很多方法未关闭数据库连接。部署至JBoss后,我在standalone.xml里配置了CCM及数据库连接日志:

<logger category="org.jboss.jca">
    <level name="DEBUG"/>
</logger>

<cached-connection-manager debug="true" error="true"/>

日志中出现数据库连接泄漏提示:

14:44:59,620 INFO  [org.jboss.jca.core.api.connectionmanager.ccm.CachedConnectionManager] (default task-19) IJ000100: Closing a connection for you. Please close them yourself: org.jboss.jca.adapters.jdbc.jdk8.WrappedConnectionJDK8@2e62903a: java.lang.Throwable: STACKTRACE
    at org.jboss.jca.core.connectionmanager.ccm.CachedConnectionManagerImpl.registerConnection(CachedConnectionManagerImpl.java:308)
    at org.jboss.jca.core.connectionmanager.AbstractConnectionManager.allocateConnection(AbstractConnectionManager.java:819)
    at org.jboss.jca.adapters.jdbc.WrapperDataSource.getConnection(WrapperDataSource.java:151)
    at org.jboss.as.connector.subsystems.datasources.WildFlyDataSource.getConnection(WildFlyDataSource.java:64)

...

    at org.xnio.XnioWorker$WorkerThreadFactory$1$1.run(XnioWorker.java:1280)
    at java.lang.Thread.run(Thread.java:748)
Caused by: javax.resource.ResourceException: IJ000151: Some connections were not closed, see the log for the allocation stacktraces
    at org.jboss.jca.core.connectionmanager.ccm.CachedConnectionManagerImpl.popMetaAwareObject(CachedConnectionManagerImpl.java:289)
    at org.jboss.as.connector.deployers.ra.processors.CachedConnectionManagerSetupProcessor$CachedConnectionManagerSetupAction.teardown(CachedConnectionManagerSetupProcessor.java:116)
    ... 13 more

但查看getConnection和returnConnection日志时,显示活跃连接为0(格式[0/100]中,总连接数为100):

返回连接日志:

15:27:42,366 DEBUG [org.jboss.jca.adapters.jdbc.local.LocalManagedConnectionFactory] (default task-25) java.sql.Connection#endRequest has been invoked
15:27:42,366 DEBUG [org.jboss.jca.core.connectionmanager.pool.strategy.OnePool] (default task-25) XXDB: returnConnection(557f1b10, false) [0/100]

移除空闲连接日志:

15:27:40,833 DEBUG [org.jboss.jca.core.connectionmanager.pool.idle.IdleRemover] (IdleRemover) Notifying pools, interval: 60000
15:27:40,833 DEBUG [org.jboss.jca.core.connectionmanager.pool.strategy.OnePool] (IdleRemover) XXDB: removeIdleConnections(1708269940833) [0/100]

获取连接日志:

15:27:41,448 DEBUG [org.jboss.jca.core.connectionmanager.pool.strategy.OnePool] (default task-25) XXDB: getConnection(null, WrappedConnectionRequestInfo@5e9a45d6[userName=xxxxxx]) [0/100]

我有两个疑问:

  1. 若活跃连接为0,是否意味着连接已返回连接池?我的理解是否正确?
  2. 若代码未关闭连接且日志显示连接泄漏,连接为何仍能返回连接池?

解答

问题1:活跃连接为0是否代表连接已返回连接池?

你的理解基本正确。日志里的[0/100]格式中,第一个数字就是当前被业务线程持有、未归还到池中的活跃连接数。当数值为0时,说明连接池内所有连接都处于空闲状态,没有被线程占用,也就是所有连接都已回到连接池。

需要注意的是:这个数值是日志打印瞬间的状态,如果代码存在连接泄漏,但泄漏的连接刚好在日志打印前被JBoss的CCM自动回收,也会出现活跃连接为0的情况——这正好匹配你遇到的场景。

问题2:代码未关连接但连接仍能返回池的原因

这完全是因为你配置的JBoss CCM(Cached Connection Manager)在起作用。你在standalone.xml中设置的<cached-connection-manager debug="true" error="true"/>,核心功能就是监控线程与连接的绑定关系:当线程执行结束(比如请求处理完成)时,CCM会检查该线程是否存在未关闭的数据库连接,若有则自动帮你关闭连接并归还到连接池,同时打印你看到的IJ000100警告日志。

简单来说:你代码里没手动关闭连接,但JBoss的CCM在线程生命周期结束时替你完成了收尾操作,把连接还回了池里,所以日志会同时出现“连接泄漏警告”和“活跃连接为0”的情况。

不过要明确:CCM只是兜底机制,不能替代代码中正确关闭连接的操作。高并发场景下,若CCM还没来得及回收泄漏的连接,新请求又占用新连接,可能导致连接池短暂耗尽;频繁的自动回收也会带来额外性能开销。正确的做法是在代码中使用try-with-resources语法,或者手动调用conn.close()关闭连接。


内容的提问来源于stack exchange,提问作者Coder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 22:31:03