0
  1. ResultSet fetches records from database.
  2. After using the resultset object we finally close the resultset.

Question is , once rs.close() is called, will it free the delete the fetched records from memory? or when JVM is facing shortage of space, garabage collector will be called to delete the resultSet?

If JVM is invoking GC when it faces shortage of memory, is it a good practice to call the Garbage collector manually in the java program to free up the space?

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Sathya
  • 15
  • 5
  • 1
    In plain Java, nothing is ever deleted directly by calling a method. The only question to ask is - "are there any references left to the data". If there are no references left, the garbage collector will collect it when it sees fit, and it's rarely necessary to "help" it. – RealSkeptic Jun 04 '19 at 15:59
  • The question [Does a ResultSet load all data into memory or only when requested?](https://stackoverflow.com/questions/858836/does-a-resultset-load-all-data-into-memory-or-only-when-requested) sort of answers your question. `ResultSet` loads records in blocks into the JVM. Once that block goes out of scope, it should be garbage collected. – Tim Biegeleisen Jun 04 '19 at 16:04
  • 2
    *"is it a good practise to call the Garbage collector manually"* No. See: [Why is it bad practice to call System.gc()?](https://stackoverflow.com/q/2414105/5221149) – Andreas Jun 04 '19 at 16:22
  • Yes, JVM will invoke the GC when it faces shortage of memory, so *no* there is no reason for triggering the GC manually, precisely for that reason, the JVM will already do when necessary and why should anyone perform an expensive operation *when unnecessary*? – Holger Jun 04 '19 at 17:28
  • @TimBiegeleisen : Thank you. If we run the same program many times, will there be many Out_Of_Scope_Blocks consuming memory and upon subsequent running of the program , the time taken to load a block = Free memory space occupied by previous blocks + Load time for new block of record – Sathya Jun 05 '19 at 07:51
  • If the program starts and completely ends, then all result sets, database connections, etc., should be completely flushed and closed. A better question, assuming your Java program is a web app, is what would happen if dozens, or hundreds, of threads come in and execute the query at the same time. – Tim Biegeleisen Jun 05 '19 at 07:53
  • @TimBiegeleisen : Can I rewrite as "If the web request is complete, and if resultSet is closed, the block of data is flushed immedietly " – Sathya Jun 05 '19 at 07:59

3 Answers3

1

Result Sets are often implemented by using a database cursor. Calling resultSet.close() will release that cursor, so it will immediately free resources in the database.

The data read by a Result Set is often received in blocks of records. Calling resultSet.close() might "release" the last block, making it eligible for GC, but that would happen anyway once the resultSet itself goes out of scope and becomes eligible for GC, and that likely happens right after calling close(), so it really doesn't matter if calling close() releases Java memory early.

Java memory is only freed by a GC run. You don't control when that happens (calling System.gc() is only a hint, you don't have control).

You're considering the wrong things. What you should focus on is:

  • Making sure resources1 are always closed as soon a possible to free up database and system resources.

    This is best done using try-with-resources.

  • Making sure you don't keep too much data, e.g. don't create objects for every row retrieved if you can process the data as you get it.

    This is usually were memory leaks occur, not inside the JDBC driver.

1) E.g. ResultSet, Statement, Connection, InputStream, OutputStream, Reader, Writer, etc.

Andreas
  • 154,647
  • 11
  • 152
  • 247
0

ResultSet.close() will immediately release all resources, except Blob, Clob and NClob objects. Release means resources will be freed when Garbage Collector decides so. Usually we don't have to worry about it.

However, some memory used by JDBC may remain used. Suppose that the driver has some sort of cache built in, and that cache is connection-scoped. To release that memory, you'd have to close JDBC Connection.

E.g. MySQL JDBC has default fetch size of 0, meaning it loads entire table into memory and keeps it in the memory for all of your statements. What's the scope of this in-memory buffer? ;)

Anyway, if you suspect memory issues, have a look at your JDBC driver specifics.

Rule of thumb, explicit GC is never good idea. But for a quick look to determine if ResultSet.close()/Connection.close() release any resources, give it a try: inspect used/free memory, close(), gc(), inspect memory again. Without explicit GC you will hardly see any changes.

jalmasi
  • 352
  • 3
  • 5
  • 2
    Your third paragraph doesnt make much sense. Although MySQL fetches the result set (and not tables!) entirely, it will not be kept for longer than the result set is open. – Mark Rotteveel Jun 04 '19 at 16:59
0

Explicit GC is a burden on JVM as it has to frequently check the memory usage and decide when to trigger it. Where as, setting the appropriate GC as per application requirement would be sufficient to handle the above scenarios.

ResultSet.close will mark the resources for garbage collection i.e. freed up the reference to mark the memory blocks as non-reachable. Also, for a jdbc, connection needs to be closed so that memory holding the connection cache can also be marked for gc.