Suppose I have a Swings Java Application, I set the min Heap is 64MB and max Heap 2GB, when the user start the application, the log in screen will be displayed, at this time the app uses 64MB, rights? From my Windows 7, I can see the java application is allocated 64MB from the Memory Resource Monitor of the OS (actually, it's more than 64MB because JVM need some memory for it's task).
After that the user does some very heavy job then the application uses 2G. Then the user log out the application, the log in screen is displayed again (the application is not closed yet). At this time the real memory that the application is using 64MB (suppose this is the perfect memory management application), but with the OS this application is still using 2G of RAM, I can see it on the resource monitor of the OS.
I want my application release the memory to the OS when it doesn't need to use a big memory. Can I do it at runtime with java app?
I mean when my application need to use 64MB of Ram, then the OS gives it 64MB only, when it need 2GB of ram then the OS gives it 2GB, after that it need 64MB of ram then the OS gives it 64MB only again, I don't want it waste 2000MB - 64MB = 1936MB.
Can I do that?
Thanks,
By default, HotSpot JVM returns the free memory to the OS but it does that very reluctantly. That is because it requires JVM to resize the heap memory which is a very CPU intensive process.
In Java, the programmer allocates memory by creating a new object. There is no way to de-allocate that memory. Periodically the Garbage Collector sweeps through the memory allocated to the program, and determines which objects it can safely destroy, therefore releasing the memory.
The Runtime#maxMemory method returns the maximum memory that the JVM will attempt to use. Once the JVM memory usage reaches this value, then it will not allocate more memory and instead, and it will garbage collect more frequently.
I have posted my test results over there. Basically, MaxHeapFreeRatio is not respected by every GC implementation, and, to make it worse, it seems to be necessary that there is enough heap activity in order to trigger it in a timely manner, ie. could be that you require 2 full GC runs to actually release the memory to the OS. And if you have a burst memory footprint of X GB, then you probably have to allocate 1 or 2 times of that amount in order to trigger the heap downsize. Or you call System.gc() manually.
If performance is not an issue, and memory footprint is all that counts, try:
-XX:UseSerialGC -Xms16M -Xminf=5 -Xmaxf=10
I want my application release the memory to the OS when it doesn't need to use a big memory. Can I do it at runtime with java app?
No you can't.
Under some circumstances, the GC will release memory back to the OS of its own accord, but I'm not aware of any JVM that allows an application to tell the GC to do this. And on top of that, the GC is rather conservative about doing this because ... as a general rule ... the JVM will operate more efficiently with more memory, and continually requesting / giving back memory to the OS is inefficient.
Note that the GC tuning option -XX:MaxHeapFreeRatio
can be used to specify the maximum ratio of free to used heap before the GC will give memory back. However, there are complications. For example, not all available GCs respect this option. If you are going to try this approach, I suggest you do some research ... and don't expect miracles.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With