Tomcat连接池数小时后driverClassName为空引发ClassNotFoundException排查
问题排查思路与解决方案
结合你描述的现象(初始连接正常,数小时后新建连接时driverClassName/URL为空引发ClassNotFoundException),以下是针对性的排查方向:
1. 排查配置被动态篡改的可能
- 检查代码中是否存在修改DataSource属性的逻辑:比如是否有自定义代码调用
setDriverClassName()、setUrl()清空了配置;是否使用了@RefreshScope等动态刷新注解,导致配置中心拉取空值覆盖原有配置;是否有BeanPostProcessor、AOP切面意外修改了DataSource的配置属性。 - 排查线程安全问题:Tomcat JDBC Pool的DataSource实例是否被多线程并发修改。可以临时添加日志,在每次获取连接前打印
getDriverClassName()和getUrl()的返回值,定位配置变为空的时间点,再结合线程栈追踪修改来源。
2. 类加载器相关问题
- 确认ojdbc包的放置位置:如果将ojdbc放在webapp的
WEB-INF/lib下,可能因Tomcat的类加载器隔离或类加载器泄漏,导致数小时后Driver类被回收,连带引发配置读取异常。建议将ojdbc移至Tomcat的lib目录,让所有webapp共享类加载。 - 开启Tomcat类加载器的FINE级日志(
org.apache.catalina.loader.WebappClassLoaderBase),查看是否存在类加载器回收、重新加载的情况,关联配置丢失的时间节点。
3. Tomcat连接池配置参数检查
- 检查连接池的维护参数:确认
testOnBorrow、testWhileIdle、validationQuery等参数是否配置正确。若连接失效后连接池尝试重建,但此时配置已丢失,就会触发异常。 - 排查遗弃连接相关配置:是否开启了
removeAbandoned、logAbandoned?若连接被标记为遗弃并清理,是否触发了意外的配置重置逻辑? - 检查JMX配置:若
jmxEnabled设为true,排查是否有通过JMX控制台误操作修改了连接池的driverClassName或URL为空。
4. Spring JDBC整合问题
- 确认DataSource的Bean定义:检查是否正确使用了
org.apache.tomcat.jdbc.pool.DataSource作为连接池实现,而非Spring的DriverManagerDataSource(无池化管理)。 - 排查Bean生命周期异常:是否存在DataSource Bean被意外销毁后重新初始化,但初始化时未注入配置的情况?可以通过Spring的Bean生命周期日志(
org.springframework.beans.factory设为FINE)查看Bean的创建、销毁时间点。
5. 增强调试手段
- 自定义DataSource子类:继承
org.apache.tomcat.jdbc.pool.DataSource,重写setDriverClassName()和setUrl()方法,在方法内打印调用栈信息,追踪是谁修改了这些属性。 - 启用线程栈快照:在配置变为空的时间点,抓取JVM线程栈(使用
jstack命令),查看当前所有线程的执行逻辑,定位可能的修改来源。
内容的提问来源于stack exchange,提问作者Jan Michálek
相关产品推荐
相关产品推荐

