Cli*_*ote 0 java sqlite memory-leaks scala jdbc
我有一些使用 JDBC 访问 SQLite 数据库的代码。
我注意到,每次进行查询时,内存使用量都会增加 - 即使在连接关闭后,内存使用量也不会下降。
这就是我正在做的:
1) 关闭PreparedStatement
2) 关闭ResultSet
3)关闭连接
这是堆转储分析的屏幕截图:
它展示了很多java.lang.ref.Finalizer很多的PreparedStatement物体ResultSet。
这是代码(它是用 scala 编写的,但应该很容易与 java 进行比较):
val conn: Connection = DriverManager.getConnection(url)
// Gets strings by a query like SELECT .. WHERE foo = ?
def getStringsByQuery(query: String, param: String, field: String):Seq[String] = {
val st = conn.prepareStatement(query)
st.setString(1, param) //value of foo = ?
st.setFetchSize(Integer.MAX_VALUE)
st.setMaxRows(Integer.MAX_VALUE)
//Holder of results
var results = collection.mutable.Seq.empty[String]
val rs: ResultSet = st.executeQuery()
//add results to holder
while (rs.next())
results :+= rs.getString(field)
rs.close() //closing ResultSet
st.close() //closing PreparedStatement
results
}
Run Code Online (Sandbox Code Playgroud)
这是我为测试这一点而编写的测试:
test("detect memory leak") {
log.info("Starting in 10 sec")
Thread.sleep(10.seconds.toMillis)
//Calls a method over and over to see if there's a memory leak or not..
(1 to 1000).par.foreach(i => {
val randomWord = getRandomWord() //this produces a random word
val sql = "SELECT foo FROM myTable where bar = ?"
val results = getStringsByQuery(sql, randomWord, "bar")
})
conn.close() //close the connection
log.info("Closed conn, closing in 30 sec")
Thread.sleep(1.minutes.toMillis)
}
Run Code Online (Sandbox Code Playgroud)
当我运行测试时 - 内存使用量从 24.6 GB 稳步增加到 33 GB 并且永远不会下降(即使 ResultSet +PreparedStatement 正在关闭),甚至在 conn 关闭并且线程休眠 1 分钟时 -内存使用量仍然没有下降。
有谁知道这是怎么回事?我将不胜感激任何帮助。
我们在生产环境中运行 sqlite-jdbc,并且在检查堆转储时注意到类似的行为。
这些对象仅位于堆上,因为它们尚未通过垃圾收集器运行。从https://blog.nelhage.com/post/third-kinds-of-leaks/的意义上来说,这是“2 类内存泄漏”,因为对象已被分配并且生存时间比您预期的要长一些。
这给我们带来的问题是,机器会在 Java 堆上保留内存非常长的时间,从而在请求高峰期间遇到内存压力。我们做了一些不同的事情来确保更频繁地收集这些对象。
这些可能与您的用例不匹配,但您可以根据您遇到的情况考虑一些选项。
| 归档时间: |
|
| 查看次数: |
1361 次 |
| 最近记录: |