Tomcat9通过JNDI获取数据库连接,停止应用报内存泄漏是否需关闭DataSource
解决方案
核心结论
你不需要主动关闭DataSource或InitialContext对象,二者均由Tomcat容器负责生命周期管理,归属权不属于当前Web应用,手动关闭反而可能导致容器运行异常。
具体修复步骤
- 修正pom.xml依赖的scope配置:
当前你的jsp-api、jstl依赖未设置<scope>provided</scope>,会被Maven自动打入WEB-INF/lib目录,和Tomcat自带的同类型类库冲突,导致类加载器无法在应用停止时被回收,引发内存泄漏。修改依赖如下:<dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.2.1-b03</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> <scope>provided</scope> </dependency> - 确保所有数据库资源被正确释放:
你从getConnection()拿到的Connection对象是连接池的借用实例,用完必须调用close()归还到连接池,否则连接池会一直持有活跃连接,应用停止时Tomcat就会报JDBC连接泄漏的警告。推荐用JDK7+自带的try-with-resources语法自动关闭资源,避免手动遗漏:// 业务代码使用连接的标准写法 try (Connection conn = YourUtils.getConnection(); PreparedStatement stmt = conn.prepareStatement("你的SQL语句"); ResultSet rs = stmt.executeQuery()) { // 处理业务逻辑 } catch (SQLException e) { // 异常处理逻辑 } - 可选优化:
你的getConnection()方法不需要每次都执行JNDI lookup查找DataSource,DataSource是容器管理的单例实例,你可以在应用启动时通过ServletContextListener一次性查找缓存,后续直接复用即可,减少不必要的JNDI查询开销。
额外排查建议
如果做完上述修改仍有警告,可以在Tomcat的conf/server.xml的<Host>标签下添加内置的泄漏预防监听器:
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
该监听器会自动处理JDBC驱动注册、线程上下文类加载器等常见的JRE层面内存泄漏问题。
内容的提问来源于stack exchange,提问作者Justtoasktheneededquestions
相关产品推荐
相关产品推荐

