Reputation: 96
I am facing a strange memory-leak issue in my recent project. I have a 'main' code which sends a message to a 'handler' code. When communicated, the handler code performs a fixed task, writes the result to disk, and exits. The fixed task is performed via a call to a specific function in another class.
During the execution of this function, the heap size increases (expectedly). However, upon the completion of the code, the result itself should not occupy a lot of space. One would expect the completion of the call to handler to result in small memory footprint. However, a 'top' shows that the handler still consumes a large amount of memory (RES).
Shouldn't a thread exit ensure that the heap consumed by the thread is reclaimed ? I tried making a System.gc() call post the execution of the function, however, it does not force a garbage collection.
Upvotes: 0
Views: 693
Reputation: 718698
The garbage collectors in Hotspot JVMs only give memory back to the operating system "reluctantly". The assumption is that the application is likely to create more objects in the space that was reclaimed. If the GC was to give the memory back, it would then need to request it again, and the churn would result in extra system calls, etcetera.
However, if the JVM notices that the heap is unnecessarily large, it will reduce the heap size, and this may eventually result in the JVM giving some memory back. The resizing mechanism is documented on this Oracle Heap Tuning Parameters page.
It should also be noted that a thread's stack is not allocated within the Java heap. Rather it lives in a non-heap memory segment that is typically requested from the OS when the thread is started, and released when the thread terminates.
Upvotes: 4
Reputation: 25623
Shouldn't a thread exit ensure that the heap consumed by the thread is reclaimed? I tried making a System.gc() call post the execution of the function, however, it does not force a garbage collection.
Try adding some JVM flags to log the GC activity:
-verbose:gc
-XX:+PrintGCTimeStamps
-XX:+PrintGCDetails
I imagine you will see that space is, in fact, being reclaimed. The memory footprint reported by top
includes space reserved for the Java heap, regardless of whether it has been used to allocate objects. You cannot reliably use those numbers to monitor GC activity.
A thread terminating will not necessarily trigger a garbage collection. Nor should you expect the process's footprint to shrink upon garbage collection. The JVM will increase the size of its managed heap as necessary, but it will not necessarily shrink it at the first opportunity (or perhaps ever). If your program's memory usage reached those levels once, then the JVM has no reason to believe it won't happen again, so unless the system memory pressure is very high, the JVM is unlikely to release that memory back to the OS immediately (if ever).
Upvotes: 2