WebLogic连接Oracle泄漏本质是Connection未真正close(),主因是代码漏关、误关或空关;典型陷阱为conn.close()时conn为null,因获取连接失败未赋值,需判空或用try-with-resources;启用Leak Profiling需同时开启Connection Profiling并设Inactive Connection Timeout非零,日志输出至server.log;泄漏定位应结合v$session、v$sql及WebLogic堆栈,警惕Statement/ResultSet未关闭导致的游标堆积。

WebLogic连接Oracle时的连接泄漏,本质是Connection对象没被真正close(),不是配置或网络问题,而是代码里漏关、误关、空关——90%以上都栽在这三类上。
Connection.close()调用但传入null怎么办
这是最隐蔽也最常复现的坑:代码里写了conn.close(),但conn变量本身是null,因为获取连接时没赋值成功(比如异常跳过、分支遗漏、变量名拼错)。
- 典型错误模式:
Connection conn = null; try { conn = dataSource.getConnection(); ... } finally { conn.close(); }—— 如果getConnection()抛异常,conn仍是null,close()就变成null.close(),JVM静默吞掉,连接实际没释放 - 正确写法必须加判空:
if (conn != null) try { conn.close(); } catch (SQLException ignored) {} - 更推荐直接用
try-with-resources,编译器自动插入close()且只对非null资源生效,杜绝空指针干扰
WebLogic控制台启用Leak Profiling后日志不输出
开了Enable Connection Leak Profiling却看不到A JDBC pool connection leak was detected日志,说明监控没真正激活或阈值未触发。
- 确认操作路径:域结构 → 数据源 → 连接池 → 高级选项 → 勾选
Enable Connection Leak Profiling和Enable Connection Profiling(后者必须同时开) -
Inactive Connection Timeout要设为非0值(如1800),否则泄漏连接不会被标记为“超时”,profiling机制不触发 - 日志默认输出到
DOMAIN_HOME/servers/<server-name>/logs/<server-name>.log</server-name></server-name>,不是console或access log,别找错位置 - 泄漏检测有延迟,需等连接闲置超过
Inactive Connection Timeout秒后才会记录,不是实时报警
查到泄漏SQL但找不到对应Java类
从v$session和v$sql能定位到慢/高频SQL(比如insert into onu_oper_record),但代码里搜不到调用点,大概率是连接被多层封装或动态代理劫持了。
- 优先检查DAO层是否用了Spring
JdbcTemplate或MyBatis,它们内部会管理Connection,但若手动调用DataSource.getConnection()又没交给模板,就会绕过自动回收 - 看调用栈是否含
weblogic.jdbc.common.internal.ConnectionEnv或weblogic.jdbc.wrapper.PoolConnection,说明连接来自WebLogic池,但被某处unwrap或强制转型后脱离了容器管控 - 在WebLogic日志中搜索该SQL的完整文本(含空格和换行),有时会被截断;也可用
SELECT sql_id, sql_text FROM v$sql WHERE sql_text LIKE '%onu_oper_record%'再关联v$active_session_history查session_id和client_info
Oracle侧v$open_cursor暴增但WebLogic池显示正常
数据库里v$open_cursor里某应用用户打开游标数飙升,但WebLogic控制台连接池“当前活动连接数”没涨——说明Connection没泄漏,但Statement/ResultSet没关,导致Oracle端游标堆积。
- 每个
Connection可打开多个Statement,每个Statement对应若干Cursor,close()Connection不等于close()Statement - 必须确保
PreparedStatement和ResultSet也在try-with-resources中声明,或显式close(),尤其注意循环内重复创建未关闭的情况 - Oracle参数
open_cursors默认常为300,查show parameter open_cursors,若接近上限,ALTER SYSTEM SET open_cursors=1000 SCOPE=BOTH只是临时缓解,根因还是代码没关资源
真正难排查的从来不是“有没有关”,而是“关的是不是当初拿到的那个”。一次getConnection()失败、两次getConnection()混用、或者AOP拦截器偷偷替换了Connection对象,都会让close()变成无效操作。盯住v$session里的prev_sql_addr和machine字段,比看代码更容易锁定真实泄漏源头。


















