Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/356.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java JDBC/SQLite内存泄漏_Java_Scala_Sqlite_Jdbc_Memory Leaks - Fatal编程技术网

Java JDBC/SQLite内存泄漏

Java JDBC/SQLite内存泄漏,java,scala,sqlite,jdbc,memory-leaks,Java,Scala,Sqlite,Jdbc,Memory Leaks,我有一些使用JDBC访问SQLite数据库的代码 我注意到,每次进行查询时,内存使用量都会增加,即使在连接关闭后,内存使用量也不会下降 以下是我正在做的: 1) 关闭PreparedStatement 2) 关闭结果集 3) 关闭连接 以下是heapdump分析的屏幕截图: 它显示了许多java.lang.ref.Finalizer和许多PreparedStatement和ResultSet对象 下面是代码(在scala中,但应该很容易与java进行比较): 以下是我编写的测试,用于测试: t

我有一些使用JDBC访问SQLite数据库的代码

我注意到,每次进行查询时,内存使用量都会增加,即使在连接关闭后,内存使用量也不会下降

以下是我正在做的:

1) 关闭
PreparedStatement

2) 关闭
结果集

3) 关闭连接

以下是heapdump分析的屏幕截图:

它显示了许多
java.lang.ref.Finalizer
和许多
PreparedStatement
ResultSet
对象

下面是代码(在scala中,但应该很容易与java进行比较):

以下是我编写的测试,用于测试:

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)
  }
当我运行测试时—内存使用量从24.6 GB稳步增加到33 GB,并且从未下降(即使ResultSet+PreparedStatement正在关闭),甚至在连接关闭且线程休眠1分钟时—内存使用量仍然没有下降


有人知道这里发生了什么吗?非常感谢您的帮助。

我们在生产环境中运行sqlite jdbc,并且在检查堆转储时注意到类似的行为

这些对象仅在堆上,因为它们尚未通过垃圾收集器运行。从某种意义上说,这是一种“类型2内存泄漏”,因为对象已经分配,并且比您预期的要长一点

这给我们带来的问题是,机器将在Java堆上保留内存,时间出乎意料地长,在请求高峰时会遇到内存压力。我们做了一些不同的事情来确保更频繁地收集这些对象

  • 减少总体Java堆大小。这可以确保垃圾收集器看到清理这些对象的更多需要。我们的工作负载在SQLite上非常紧张,因此机器内存最好通过JNI进入堆外内存,而不是在Java堆上分配
  • 调整G1GC垃圾收集器,以便为newgen分配更多堆,因为这些对象通常寿命很短。()
  • 增加垃圾收集器日志记录,并通过GCEasy()之类的服务运行它们,以准确了解正在进行的垃圾收集器运行类型,以便进行进一步的调优

<>这些可能与你的用例不匹配,但是这些是你可以根据你所遇到的问题考虑的一些选项。

< P>我通过将我的SQLite数据集移植到CQEngine来解决这个问题。非常高兴。

我关闭了连接和数据库对象,创建了一个具有相同参数和新连接的新对象数据库,最后称为垃圾收集

根据需要重复此过程。我做了一个计数器,当我填满电脑的一半内存时,重复这个过程


现在我可以正常运行了。

关闭连接每次迭代无差异@user7294900I还更新到了最新版本的SQLite驱动程序-无差异ID您尝试添加try子句了吗?@user7294900我相信在这种情况下不必这样做,因为资源正在直接关闭,没有任何异常发生嘿tildedave—您是否也使用JDBC访问SQLite?您是否也看到未进行GC的PreparedStatements/ResultSet?它们最终是GC的吗?如果是,大约需要多长时间?是的,我们使用xerial sqlite库运行sqlite jdbc,基本上就像你的问题一样。这些服务一次运行几天或几周。(将答案编辑得更清楚一点。)我不确定收集对象的时间尺度。它确实取决于您如何配置垃圾收集器,因此,如果您发现问题(超出测试用例),您可以开始查找。您是否能够共享您最终使用的GC设置?因此,我们的GC设置非常特定于我们的应用程序,我不确定它们是否普遍有用。我们得到的主要好处是减少了堆的大小,如果您在应用程序中发现内存问题,我将从这一点开始。我们目前还覆盖了InitiatingHeapOccupencyPercent(更频繁地使用GC)、G1OldCsetRegionResholdPercent(更频繁地使用GC)、G1MaxNewSizePercent(为新对象提供更多堆空间),这也很有帮助。
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)
  }