Memory/Heap JDBC 中关闭 ResultSet 后的状态
Memory/Heap Status after closing ResultSet in JDBC
- ResultSet 从数据库中获取记录。
- 使用结果集对象后,我们最终关闭了结果集。
问题是,一旦 rs.close() 被调用,它会从内存中释放并删除获取的记录吗?
要么
当JVM面临不足space时,会调用garabage collector删除resultSet吗?
如果 JVM 在遇到内存不足时调用 GC,在 java 程序中手动调用垃圾收集器以释放 space 是一个好习惯吗?
结果集通常通过使用数据库游标来实现。调用 resultSet.close()
将释放该游标,因此它将立即释放数据库 中的资源 .
结果集读取的数据通常在 块 记录中接收。调用 resultSet.close()
可能 "release" 最后一个块,使其符合 GC 的条件,但是一旦 resultSet
本身超出范围并符合 GC 的条件,这无论如何都会发生,而且这很可能发生在调用 close()
之后,所以调用 close()
是否提前释放 Java 内存并不重要。
Java 内存仅由 GC 运行 释放。你无法控制何时发生这种情况(调用 System.gc()
只是一个 提示 ,你没有控制权)。
你考虑错了。你应该关注的是:
确保资源1总是尽快关闭以释放数据库和系统资源。
最好使用 try-with-resources.
确保你不要保留太多数据,例如如果您可以在获取数据时对其进行处理,则不要为检索到的每一行都创建对象。
这通常是发生内存泄漏,而不是在 JDBC 驱动程序内部。
1) 例如ResultSet
、Statement
、Connection
、InputStream
、OutputStream
、Reader
、Writer
等
ResultSet.close() 将立即释放 所有资源,Blob、Clob 和 NClob 对象除外。 Release 表示资源将在垃圾收集器决定时释放。通常我们不用担心。
但是,JDBC 使用的一些内存可能会继续使用。
假设驱动程序内置了某种缓存,并且该缓存是 connection-scoped。要释放该内存,您必须关闭 JDBC 连接。
例如MySQL JDBC 的默认提取大小为 0,这意味着它会将整个 table 加载到内存中,并将其保存在内存中以供您的所有语句使用。这个 in-memory 缓冲区的范围是什么? ;)
无论如何,如果您怀疑内存问题,请查看您的 JDBC 驱动程序细节。
根据经验,显式 GC 从来都不是好主意。但是要快速查看 ResultSet.close()/Connection.close() 是否释放任何资源,请尝试一下:inspect used/free memory, close(), gc(), inspect memory再次。如果没有明确的 GC,你几乎看不到任何变化。
显式 GC 是 JVM 的负担,因为它必须经常检查内存使用情况并决定何时触发它。其中,根据应用程序要求设置适当的 GC 足以处理上述情况。
ResultSet.close 会将资源标记为垃圾回收,即释放引用以将内存块标记为 non-reachable。另外,对于jdbc,需要关闭连接,这样保存连接缓存的内存也可以被标记为gc。
- ResultSet 从数据库中获取记录。
- 使用结果集对象后,我们最终关闭了结果集。
问题是,一旦 rs.close() 被调用,它会从内存中释放并删除获取的记录吗? 要么 当JVM面临不足space时,会调用garabage collector删除resultSet吗?
如果 JVM 在遇到内存不足时调用 GC,在 java 程序中手动调用垃圾收集器以释放 space 是一个好习惯吗?
结果集通常通过使用数据库游标来实现。调用 resultSet.close()
将释放该游标,因此它将立即释放数据库 中的资源 .
结果集读取的数据通常在 块 记录中接收。调用 resultSet.close()
可能 "release" 最后一个块,使其符合 GC 的条件,但是一旦 resultSet
本身超出范围并符合 GC 的条件,这无论如何都会发生,而且这很可能发生在调用 close()
之后,所以调用 close()
是否提前释放 Java 内存并不重要。
Java 内存仅由 GC 运行 释放。你无法控制何时发生这种情况(调用 System.gc()
只是一个 提示 ,你没有控制权)。
你考虑错了。你应该关注的是:
确保资源1总是尽快关闭以释放数据库和系统资源。
最好使用 try-with-resources.
确保你不要保留太多数据,例如如果您可以在获取数据时对其进行处理,则不要为检索到的每一行都创建对象。
这通常是发生内存泄漏,而不是在 JDBC 驱动程序内部。
1) 例如ResultSet
、Statement
、Connection
、InputStream
、OutputStream
、Reader
、Writer
等
ResultSet.close() 将立即释放 所有资源,Blob、Clob 和 NClob 对象除外。 Release 表示资源将在垃圾收集器决定时释放。通常我们不用担心。
但是,JDBC 使用的一些内存可能会继续使用。 假设驱动程序内置了某种缓存,并且该缓存是 connection-scoped。要释放该内存,您必须关闭 JDBC 连接。
例如MySQL JDBC 的默认提取大小为 0,这意味着它会将整个 table 加载到内存中,并将其保存在内存中以供您的所有语句使用。这个 in-memory 缓冲区的范围是什么? ;)
无论如何,如果您怀疑内存问题,请查看您的 JDBC 驱动程序细节。
根据经验,显式 GC 从来都不是好主意。但是要快速查看 ResultSet.close()/Connection.close() 是否释放任何资源,请尝试一下:inspect used/free memory, close(), gc(), inspect memory再次。如果没有明确的 GC,你几乎看不到任何变化。
显式 GC 是 JVM 的负担,因为它必须经常检查内存使用情况并决定何时触发它。其中,根据应用程序要求设置适当的 GC 足以处理上述情况。
ResultSet.close 会将资源标记为垃圾回收,即释放引用以将内存块标记为 non-reachable。另外,对于jdbc,需要关闭连接,这样保存连接缓存的内存也可以被标记为gc。