JDK-6498735 : JVM should be able to fully release allocated memory
  • Type: Enhancement
  • Component: hotspot
  • Sub-Component: gc
  • Affected Version: 6
  • Priority: P5
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2006-11-29
  • Updated: 2014-09-10
  • Resolved: 2014-09-10
Description
A DESCRIPTION OF THE REQUEST :
It would be a great feature if the JVM could be told to actually release allocated memory back to the system, so that the actual system memory footprint was reduced.

The JVM now steadily increases memory usage up to -Xmx (plus all other shared stuff). In some scenarios, it would be very fortunate if one could get it to decrease its usage drastically "upon request".

System.gc() asks the JVM to do a garbage collect. A System.release() (or something like that) could ask the JVM to actually release the allocated memory.

JUSTIFICATION :
My need revolves round a "systray" feature, where the application will "minimize to tray" but still have an limited feature set while it's docked there. However, if the user doubleclicks, it should "load up" again, going back to full functionality.

However, in this specific scenario, the "full application" is a huge memory-hog (its a high-caching image-oriented thingy), and will try to gobble up as much memory as possible while fully active. Thus, it's very unfortunate that if the user "minimizes to tray" to leave the application's main functionality, the application still have allocated 1 GB or more of the system's memory (which even if swapped to disk will give the user a problem).

Such a memory-releasing feature would thus be great: When the user "minimizes to tray", the application would let go of all its memory-buffers and other resources, ditch the full app's classloader to unload most classes, and then do a System.release() (or whatever procedure that was deemed the correct here) to actually fully release memory back to the OS.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Upon System.release(), the JVM would shrink its memory allocation down to absolute minimum (or -Xmn if set) to contain the currently active set of objects and classes.
ACTUAL -
The JVM will allocate memory up to the -Xmx mark (and obviously way above due to the JVM and dependent libs itself), but wont shrink.

CUSTOMER SUBMITTED WORKAROUND :
Have some small native application (or another instance of the JVM) that executes the application, where "minimize to tray" actually exits the full app JVM.

A couple of solutions for how the tray features would be handled compared to the full-app:
  1) The tray-features is contained in this wrapper application
  2) The tray-features is contained in another application, so the wrapper application basically alternates between starting the full-app or the tray-app.
  2) The wrapper simply restarts the main app, which then starts in minimized mode by not loading the full app, and not allocating all its buffers and whatevers. Then when the user clicks "activate", it loads the rest of the app.

PS: Why can't this annoying junky bug database load my "sun online account id" itself when I'm logged in?!

Comments
The referenced JDK-8055594 JEP provides a way to tell the GC to be more economic with java heap memory. This could be used to tell the VM to use less heap in the given use case. There are also the manageable flags Min- and MaxFreeRatio that allow the application to set the free space that should be kept back. Apart from that all collectors attempt to give back memory on system.gc() already.
10-09-2014

"Both parallel collectors do require a number of GCs before shrinking the heap down to an "acceptable" size. This is per design. They are deliberately holding on to the heap assuming that it will be needed in the future. Setting the flag -XX:GCTimeRatio=1 will improve the situation somewhat but it will still take several GCs to shrink a lot." Echoing Jesper's second paragraph of observations. Basically, we have to await at least two GC's to resize the heap correctly (based on my experience working on ParallelGC resizing policy).
23-09-2013

I have verified that G1 (-XX:+UseG1GC), Parallel scavenge (-XX:+UseParallelGC) and ParallelOld (-XX:+UseParallelOldGC) do return memory when the heap shrinks. I'm not so sure about Serial and CMS, they didn't shrink their heap in my experiments. Both parallel collectors do require a number of GCs before shrinking the heap down to an "acceptable" size. This is per design. They are deliberately holding on to the heap assuming that it will be needed in the future. Setting the flag -XX:GCTimeRatio=1 will improve the situation somewhat but it will still take several GCs to shrink a lot. G1 is remarkably good at shrinking the heap fast, so for the usecase described above I would say it's solvable by using G1 and running System.gc() after having released all cashes and class loaders etc. Is this an acceptable workaround?
23-09-2013

EVALUATION The HotSpot JVM already will release memory back to the operating system if it is not needed for live Java objects. If you can arrange to get a notification that the application is being asked to "minimize to tray", you can drop your references to items in your caches, remove all references to classes and classloaders so they can be collected. It might be difficult to find and release all those references. (But, unless you do, the JVM won't be able to release them for you.) There is some damping in the amount the JVM will shrink at each collection (as there is a damping so we don't just grow to -Xmx until we need the space). Repopulating a 1GB heap will take a while, so the performance of an application that minimized that aggressively would probably be terrible while it was coming back from being minimized. I'm tempted to close this as "not a bug".
29-11-2006