连接池“泄漏”正在开发中。可能是由于JUnit测试设置?

时间:2011-03-10 14:41:46

标签: java jdbc junit glassfish cactus

我正在尝试在开发中追踪数据库连接池“泄漏”,我想知道它是否是由单元测试的设置方式产生的。有些东西正在从Glassfish池中获取数据库连接,并且在完成后不会关闭它们。最终,池最大连接用完,应用程序无法获得任何新的数据库连接。

我们的JUnit测试在setUp()方法中从池中获取连接,然后在tearDown()方法中关闭该连接。我们可以确定tearDown()方法总是会运行吗?如果发生未处理的异常,是否可以绕过tearDown()方法?

关于我们应该寻找什么的任何其他想法?

我应该注意到我们正在使用Jakarta Cactus在Glassfish应用服务器上运行这些单元测试。

3 个答案:

答案 0 :(得分:1)

时会将连接返回到池中
  1. 当您以实用方式关闭它时,会将连接返回到池中(最后阻止!)
  2. 发生完整垃圾收集
  3. 当java进程被终止时(停止服务器,单元循环结束)
  4. 简而言之,运行单元测试不太可能导致池化问题。

答案 1 :(得分:1)

防止和报告数据库连接泄漏的一个建议:

首先找出每个连接的范围。

示例,对于许多Web应用程序,请求范围内需要连接。

定义范围后,您需要做的就是在范围生命周期结束时以确定的方式关闭连接。

断言Web应用程序中始终关闭数据库连接的一种方法是创建一个servlet过滤器,该过滤器将在请求进入时获取连接,并在发送响应时关闭连接。通过将连接放入ThreadLocal变量,可以将连接从过滤器传递给其他对象。

范围的另一个示例是每个事务需要连接时。您可能希望使用Execute Around Method模式在范围开始之前获取连接,并以确定的方式在结束时关闭它。

如果您实施上述任何想法,您甚至可以在关闭之前记录哪些连接没有关闭,以帮助识别泄漏。

祝你好运,我希望这有帮助,请让我知道。

更新

我刚刚通过向数据库连接池实现apache DBCP添加调试参数来解决遗留代码中的数据库连接泄漏问题。 即使您不想在生产中使用DBCP,您仍然可以在测试中将其设置为检测借用未闭合连接的确切行代码。

在我的环境中,我使用了tomcat和JNDI数据源配置,如下所示:

  <Resource auth="Container"
       name="jdbc/APP_NAME"
       username="user"
       password="password"
       url="jdbc:oracle:thin:@server.domain:1521:development"    
       type="javax.sql.DataSource"
       driverClassName="oracle.jdbc.driver.OracleDriver"

       maxIdle="10"
       maxWait="5000"
       maxActive="10"
       validationQuery="select 1 from dual"
       validationInterval="30000"
       testOnBorrow="true"
       testOnReturn="false"
       testWhileIdle="true"
       timeBetweenEvictionRunsMillis="5000"
       numTestsPerEvictionRun="3"
       minEvictableIdleTimeMillis="30000"


 <!-- These 3 settings saved me hours of headache -->

 logAbandoned="true" <!-- Will report the stacktrace of the faulty code --> 

 removeAbandoned="true" <!-- Will remedy the connection starvation while leaky code is not fixed-->

 removeAbandonedTimeout="60"<!-- Interval for fixing connection starvation while leaky code is not fixed-->

 />

请参阅:Apache DBCP configuration

答案 2 :(得分:0)

我从来没有看到如果它是一个正确的tearDown(正确的方法signatur或注释取决于JUnit版本)会丢失tearDown

但是:当在tearDown中抛出异常时,你可能会跳过tearDown的部分内容。

我通过运行TestSuite并观察连接池来测试您的理论。听起来很容易。