HikariCP 报 Connection leak detection triggered 是因获取的 Connection 未在 leakDetectionThreshold 内关闭;需显式配置该阈值(如60000),日志定位 getConnection() 调用点,重点排查手动获取连接未关闭、异常分支遗漏、异步持有、代理未转发 close、Spring 事务失效及 Oracle 驱动兼容性等问题。

为什么 HikariCP 会报 Connection leak detection triggered
HikariCP 在 Java 11 下检测到连接泄漏时,不是连接真的“丢了”,而是某个 Connection 被 getConnection() 获取后,没在配置的超时时间内调用 close()。Java 11 的 java.sql.Connection 是 AutoCloseable,但 HikariCP 不依赖 try-with-resources 自动回收——它靠自己的定时器+弱引用跟踪每个借出的连接。一旦超过 leakDetectionThreshold(默认 0,即关闭),就会触发日志并打印堆栈。
常见诱因包括:
- 手动获取
Connection后忘了close(),尤其在异常分支里漏写 - 用了 Spring 的
JdbcTemplate或DataSourceUtils,但没走 Spring 的事务或模板封装逻辑(比如直接从DataSource拿连接) - 异步线程中持有连接未释放(如
CompletableFuture.supplyAsync里用了Connection) - 连接被包装成自定义代理对象,且代理未正确转发
close()
怎么开启并解读泄漏检测日志
必须显式启用泄漏检测,否则不会报。在 HikariCP 配置中加:
leakDetectionThreshold=60000
单位是毫秒,建议设为略大于你最长 SQL 执行时间(例如 30s 的慢查询,可设 45000)。注意:leakDetectionThreshold 必须 > 0 才生效;设为 0 或不配,等于关闭检测。
触发后日志类似:
WARN HikariPool-1 - Connection leak detection triggered for connection com.zaxxer.hikari.pool.HikariProxyConnection@1a2b3c4d on thread http-nio-8080-exec-7, stack trace follows
java.lang.Exception: Apparent connection leak detected
at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:123)
at com.example.dao.UserDao.find(UserDao.java:45)
...
关键信息是 on thread ... 和后续堆栈——它定位的是 getConnection() 调用点,不是 close() 缺失点。所以你要顺着这个堆栈,找到对应方法里所有可能未关闭连接的路径。
排查时重点检查哪些代码模式
不要只盯 DAO 层,优先扫这些高危模式:
- 所有显式调用
dataSource.getConnection()的地方,确认是否包在try-with-resources或手动finally { conn.close(); }中 - 使用
PreparedStatement或ResultSet时,是否只关了其中一个?HikariCP 不管子资源,但子资源未关可能导致连接无法真正归还(尤其 Oracle JDBC 驱动对ResultSet.close()有强依赖) - Spring 环境下,是否误用
@Transactional但方法抛出非运行时异常(默认只回滚RuntimeException),导致事务未提交/回滚,连接卡在事务中不释放 - 是否在 Lambda 表达式或匿名内部类里捕获了
Connection变量,造成隐式延长生命周期(尤其结合ThreadLocal或缓存)
Oracle JDBC + Java 11 的特殊注意事项
Oracle 官方驱动(ojdbc8.jar)在 Java 11 上对连接状态管理更严格,容易放大泄漏表现:
- 确保用的是
ojdbc8(支持 Java 11),别混用ojdbc6(仅到 Java 8)——后者在 Java 11 下可能出现 close 失效但无异常 - Oracle 连接默认开启
autoCommit=false,如果应用没显式 commit/rollback,连接归还池时会处于“挂起事务”状态,HikariCP 认为它仍在使用,可能延迟回收甚至拒绝归还 - 检查
HikariConfig是否设置了connectionInitSql=ALTER SESSION SET CURRENT_SCHEMA=xxx类语句——这类初始化 SQL 若失败,会导致连接无法加入池,但错误可能被吞掉,表现为“连接变少+无日志”
最隐蔽的一点:Oracle 的 Connection.isValid(int) 在某些网络抖动场景下会阻塞,而 HikariCP 的连接回收逻辑会调用它。如果这个调用卡住,连接就一直无法真正关闭。可以临时设 validationTimeout=2000 控制验证上限。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











