【问题标题】:Memory/Heap Status after closing ResultSet in JDBC在 JDBC 中关闭 ResultSet 后的内存/堆状态
【发布时间】:2019-10-20 04:37:09
【问题描述】:
  1. ResultSet 从数据库中获取记录。
  2. 使用结果集对象后,我们最终关闭了结果集。

问题是,一旦 rs.close() 被调用,它会释放从内存中删除获取的记录吗? 要么 当JVM面临空间不足时,会调用garabage collector来删除resultSet?

如果JVM在内存不足时调用GC,在java程序中手动调用垃圾收集器来释放空间是不是一个好习惯?

【问题讨论】:

  • 在纯 Java 中,不会通过调用方法直接删除任何内容。唯一要问的问题是 - “是否有任何对数据的引用”。如果没有剩下的引用,垃圾收集器会在它认为合适的时候收集它,并且很少需要“帮助”它。
  • 问题Does a ResultSet load all data into memory or only when requested? 可以回答您的问题。 ResultSet 将块中的记录加载到 JVM 中。一旦该块超出范围,它应该被垃圾回收。
  • “手动调用垃圾收集器是不是一个好习惯” 否。见:Why is it bad practice to call System.gc()?
  • 是的,JVM在内存不足时会调用GC,所以no没有理由手动触发GC,正因为如此,JVM已经必要时做,为什么有人要在不必要时执行昂贵的操作?
  • @TimBiegeleisen:谢谢。如果我们多次运行同一个程序,是否会有很多 Out_Of_Scope_Blocks 消耗内存,并且在程序后续运行时,加载一个块所用的时间 = 先前块占用的空闲内存空间 + 新记录块的加载时间

标签: java jdbc garbage-collection


【解决方案1】:

结果集通常通过使用数据库游标来实现。调用resultSet.close() 将释放该游标,因此它将立即释放数据库中的资源

结果集读取的数据通常以记录的形式接收。调用 resultSet.close() 可能会“释放”最后一个块,使其符合 GC 条件,但是一旦 resultSet 本身超出范围并符合 GC 条件,就会发生这种情况,并且这很可能在调用 close() 之后立即发生,所以调用close()是否提前释放Java内存并不重要。

Java 内存仅由 GC 运行释放。你无法控制何时发生(调用System.gc() 只是一个提示,你无法控制)。

你在考虑错误的事情。你应该关注的是:

  • 确保资源1 总是尽快关闭以释放数据库系统 资源。

    最好使用 try-with-resources

  • 确保不要保留太多数据,例如如果您可以在获取数据时对其进行处理,请不要为检索到的每一行创建对象。

    这通常是发生内存泄漏,而不是在 JDBC 驱动程序内部。

1) 例如ResultSetStatementConnectionInputStreamOutputStreamReaderWriter

【讨论】:

    【解决方案2】:

    ResultSet.close() 将立即释放所有资源,除了 Blob、Clob 和 NClob 对象。 Release 表示资源将在垃圾收集器决定时释放。通常我们不必担心。

    但是,JDBC 使用的一些内存可能仍会被使用。 假设驱动程序内置了某种缓存,并且该缓存是连接范围的。要释放该内存,您必须关闭 JDBC 连接。

    例如MySQL JDBC 的默认提取大小为 0,这意味着它将整个表加载到内存中,并将其保存在内存中以供所有语句使用。这个内存缓冲区的范围是什么? ;)

    无论如何,如果您怀疑内存问题,请查看您的 JDBC 驱动程序细节。

    经验法则,显式 GC 绝不是好主意。但是要快速查看 ResultSet.close()/Connection.close() 是否释放任何资源,请尝试一下:检查已用/空闲内存,close(),gc(),再次检查内存。如果没有显式 GC,您几乎看不到任何变化。

    【讨论】:

    • 你的第三段没有多大意义。尽管 MySQL 完全获取结果集(而不是表!),但它不会保留超过结果集打开的时间。
    【解决方案3】:

    显式 GC 是 JVM 的负担,因为它必须经常检查内存使用情况并决定何时触发它。而根据应用需求设置合适的 GC 就足以处理上述场景了。

    ResultSet.close 将标记资源进行垃圾回收,即释放引用以将内存块标记为不可访问。此外,对于 jdbc,连接需要关闭,以便保存连接缓存的内存也可以标记为 gc。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-26
      • 1970-01-01
      • 2019-03-20
      • 2019-04-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多