【问题标题】:MS SQL JDBC driver create memory leak with JNDI Hikari on Tomcat 9MS SQL JDBC 驱动程序在 Tomcat 9 上使用 JNDI Hikari 创建内存泄漏
【发布时间】:2018-05-09 08:30:21
【问题描述】:

我在 Tomcat 9.0.7 上使用 JNDI + HikariCP,配置如下:

 <Resource name="jdbc/mydb" auth="Container"
      factory="com.zaxxer.hikari.HikariJNDIFactory"
      type="javax.sql.DataSource"
      minimumIdle="5" 
      maximumPoolSize="20"
      connectionTimeout="300000"
      dataSourceClassName="com.microsoft.sqlserver.jdbc.SQLServerDataSource"
      dataSource.url="jdbc:sqlserver://server:1433;databaseName=mydb"      
      dataSource.user="fantomas"
      dataSource.password="somepassword" 
      closeMethod="close"
      />

当我在没有部署任何 WAR 的情况下运行 tomcat(仅标准安装,仅此而已)时,Catalina 日志中出现以下警告:

09-May-2018 10:15:16.971 WARNING [main] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [host-manager] appears to have started a thread named [mssql-jdbc-TimeoutTimer-1] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
 sun.misc.Unsafe.park(Native Method)
 java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
 java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:460)
 java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:362)
 java.util.concurrent.SynchronousQueue.poll(SynchronousQueue.java:941)
 java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1073)
 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
 java.lang.Thread.run(Thread.java:748)

出了什么问题,为什么会出现泄漏?我该如何解决?

UPDATE-1 Tomcat安装./lib中的自定义库有:

ms-sql-6.4.0.jre8.jar 
slf4j-api-1.7.25.jar 
HikariCP-2.7.8.jar 

UPDATE-2 Hikari 3.1.0 & Tomcat 9.0.8 也有同样的问题

【问题讨论】:

    标签: sql-server tomcat jndi hikaricp


    【解决方案1】:

    有问题的线程 (mssql-jdbc-TimeoutTimer) 属于 MSSQL 驱动程序。当您使用 HikariCP 而不是 Tomcat JDBC 时,它会显示出来,因为 HikariCP 适当地使用 JDBC 超时 API 来提高可靠性。

    这是 MSSQL 驱动程序search for 'mssql-jdbc-TimeoutTimer' here 的一个已知问题。

    似乎计时器是由 HikariCP 对Connection.isValid() 的 MSSQL 驱动程序实现的调用启动的。因此,您或许可以通过设置connectionTestQuery 来避免该问题,这将禁用isValid()

    【讨论】:

    • 谢谢,在 Tomcat 9.0.8 上使用 connectionTestQuery="SELECT 1" 进行了测试并且可以正常工作。
    • 谁能弄清楚 Github 的实际问题是什么?可能是这个,但它被标记为已解决。 github.com/Microsoft/mssql-jdbc/issues/150
    【解决方案2】:

    Related issuereported to hikari 类似的泄漏,似乎最终的解决方案不使用 Hikari JNDI 工厂,而是使用 Tomcat 的数据源

    尝试将工厂更改为:

    factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
    

    编辑

    您为 Hikari 创建了一个新的issue

    【讨论】:

    • 这将使用 Tomcat 自己的数据库池而不是 Hikari 池。但我们想使用 Hikari 池,因为性能更好。 Hikari 池有什么解决方案吗?
    • @kulatamicuda 我建议你向github.com/brettwooldridge/HikariCP/issues/new提出一个包含完整细节的问题
    • 按建议上报到github
    猜你喜欢
    • 2012-11-25
    • 2018-02-09
    • 1970-01-01
    • 2012-12-28
    • 2012-08-06
    • 2019-01-25
    • 2014-11-28
    • 2013-09-06
    相关资源
    最近更新 更多