MS SQL JDBC驱动程序在Tomcat 9上使用JNDI Hikari创建内存泄漏

时间:2018-05-09 08:30:21

标签: sql-server tomcat jndi hikaricp

我在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&amp; Tomcat 9.0.8

2 个答案:

答案 0 :(得分:2)

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

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

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

答案 1 :(得分:0)

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

尝试将工厂更改为:

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

修改

您为Hikari

创建了新的issue