[英]HikariCP NullPointerException
我們正在嘗試將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驅動程序是ojdbc-7,版本為12.1.0.2。 池使用以下配置:
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
是錯誤還是配置錯誤?
我不確定100%,但看起來像是:
close()
之后,您將退出連接,這是不允許的。 要么.. close()
,這是不允許的。 退出連接時,您必須是該連接的所有者(從getConnection()
獲得,並且隨后您必須不close()
連接(它將自動關閉)。如上所述,如果調用了close()
已經存在,則該連接已經返回到池中,因此將其逐出是無效的,因為您不再是所有者。
編輯:讓我更清楚。 通過研究如何實現此異常,您似乎很清楚,首先要關閉連接,然后逐出連接。 反向(先退出然后關閉)不會導致此錯誤。
這稱為“返回后使用”,類似於沒有垃圾回收的語言中的“免費使用后”錯誤。 關閉連接后,它會返回到池中。 從那一刻起,該連接就可以被另一個線程聲明了-close close()
的調用者不再是所有者。
這完全類似於在C / C ++中在內存上調用free()
。 這樣做之后,立即可以由另一個調用方聲明該內存-free free()
的調用方不再是所有者。 在C / C ++情況下,如果繼續使用對釋放的內存的引用,則可能會損壞已分配該內存的另一個線程的數據。
對於Java中幾乎所有的池庫(連接或其他),一旦將對象釋放回池中,您就不再是所有者。 沒有什么可以阻止您保留對返回對象的引用。
在這種情況下,一旦調用close()
,該對象將立即返回到池中。 如果另一個線程從池( getConnection()
)合法獲取連接,而同時先前的所有者調用evict()
,則您很容易遇到此問題。
我們可以選擇強化(或不強化)此代碼路徑。 HikariCP在哲學上並不是特別的家長式管理。 偏愛文檔而不是代碼。 例如,如果將null
傳遞給evict()
,則在某處會遇到NPE。 我們可以檢查null
並忽略它嗎? 當然。 在整個代碼庫中乘以該方法,它很容易增長20%。 或者,不這樣做,開發人員呢?
這是一個相當簡單的合同:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.