我们正在尝试将HikariCP (版本2.4.4)集成到我们的应用程序中。在使用了一段时间之后,池无法获得新的连接,引发:
java.lang.NullPointerException
at com.zaxxer.hikari.pool.PoolBase.setNetworkTimeout(PoolBase.java:464) ~[HikariCP-2.4.4.jar:?]
at com.zaxxer.hikari.pool.PoolBase.isConnectionAlive(PoolBase.java:131) ~[HikariCP-2.4.4.jar:?]
at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:171) ~[HikariCP-2.4.4.jar:?]
at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:147) ~[HikariCP-2.4.4.jar:?]
at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:83) ~[HikariCP-2.4.4.jar:?]我们使用的jdbc驱动程序是版本12.1.0.2的ojdbc-7。池使用以下配置:
allowPoolSuspension.............false
autoCommit......................false
catalog.........................null
connectionInitSql..............."BEGIN EXECUTE IMMEDIATE 'SET ROLE SOME_ROLE IDENTIFIED BY SOME_PASSWORD '; END;"
connectionTestQuery............."SELECT 1 FROM DUAL"
connectionTimeout...............15000
dataSource......................null
dataSourceClassName.............null
dataSourceJNDI..................null
dataSourceProperties............{v$session.machine=host, password=<masked>, v$session.program=my application}
driverClassName................."oracle.jdbc.OracleDriver"
healthCheckProperties...........{}
healthCheckRegistry.............null
idleTimeout.....................60000
initializationFailFast..........true
isolateInternalQueries..........false
jdbc4ConnectionTest.............false
jdbcUrl........................."jdbc:oracle:thin:@//host.company.com:1521/database.company.com"
leakDetectionThreshold..........1800000
maxLifetime.....................0
maximumPoolSize.................18
metricRegistry..................null
metricsTrackerFactory...........null
minimumIdle.....................2
password........................<masked>
poolName........................"TEST_POOL"
readOnly........................false
registerMbeans..................false
scheduledExecutorService........null
threadFactory...................null
transactionIsolation............null
username........................"USER_NAME"
validationTimeout...............5000是错误还是错误配置?
发布于 2016-03-07 12:14:39
我不是百分之百确定,但看起来
close()之后,您正在取消一个连接,这是不允许的。或者..。close(),这是不允许的。当您退出一个连接时,您必须是该连接的所有者(从getConnection()获得,随后您不能close()该连接(它将自动关闭)。正如上面所解释的,如果您已经调用了close(),则连接已经返回到池中,并且由于您不再是所有者,因此驱逐它是无效的。
编辑:让我说得更清楚。通过研究如何达到此异常,似乎可以清楚地看到,您首先要关闭连接,其次是取消连接。反向(驱逐,然后关闭)不会导致此错误。
这被称为“返回后使用”,类似于在没有垃圾收集的语言中“使用后免费”的bug。当您关闭连接时,它将返回到池中。从那一刻起,连接就可以由另一个线程声明-- close()的调用者不再是所有者。
这与调用C/C++中的内存中的free()完全类似。在这样做之后,内存就可以被另一个调用方调用-- free()的调用者不再是所有者了。在C/C++情况下,如果您继续使用对已释放内存的引用,则可能会破坏另一个已分配它的线程的数据。
在Java中几乎所有池库(连接或其他)的情况下,一旦将对象释放回池,您就不再是所有者。没有什么可以阻止您保留对返回对象的引用。
在这种情况下,一旦调用了close(),对象就会立即返回到池中。如果另一个线程合法地从池(getConnection())获得连接,而前面的所有者同时调用evict(),则很容易遇到此问题。
我们可以选择加强这个代码路径(或不)。HikariCP在哲学上并不是特别家长式的,它更倾向于文档而不是代码。例如,如果您将一个null传递给evict(),您将在某个地方遇到一个NPE。我们能检查一下null并忽略它吗?好的。将这一方法乘以代码基,它很容易增长20%。或者,不要那样做,开发人员?
这是一个相当简单的合同:
https://stackoverflow.com/questions/35840631
复制相似问题