This week's book giveaway is in the OO, Patterns, UML and Refactoring forum. We're giving away four copies of Refactoring for Software Design Smells: Managing Technical Debt and have Girish Suryanarayana, Ganesh Samarthyam & Tushar Sharma on-line! See this thread for details.
Probably in the wrong area - please move if necessary!
I'm pretty sure that I know the answer to this, and that it's "don't be ridiculous", but I thought I'd ask...
I have an application, with a component that I have no control over which is quite memory hungry, but it doesn't need *that* much for normal activity. I can set the JVM's maximum memory argument to 256MB (-Xmx256M), and it works perfectly happily 95% of the time. HOWEVER, there are a few situations where I'd like to be able to grant it up to 512MB (I know it's a lot, but I need it). As I understand it, the OS will handle it if that's more memory than is available, presumably by paging to the hard disk.
I don't want to set it to use 512MB all the time, because that's obviously too high, and my app will just use it all before garbage collecting, which means that if you have anything else running (or less than 512MB RAM) it seems to hang for ages every now and then, presumably paging to the disk (the hard drive light goes crazy). If I have it down at 256MB, Java crashes with an OutOfMemoryError in those 5% of situations.
So, the inevitable question is: is there some way to either tell the JVM, "Use up to 512MB, but only if you *really* need it, otherwise stay down nearer the 256MB mark", or to set the limit dynamically, so for my memory-hungry processes I can up it, and then bring it down straight afterwards?
Other suggestions are obviously welcome, within the constraints that it must be Java, that I have no (little, but effectively no) control over the component and its memory usage, and that the software is due to be released next week...
You can use the -XX:MinHeapFreeRatio and -XX:MaxHeapFreeRatio options (specific to the Sun JVM but also available on Mac, I think).
In a situation where there is a difference between the -Xms and the -Xmx values for min and max heap size, the above -XX parameters control when the heap will be expanded and when it will be shrunk.
The default value of -XX:MinHeapFreeRatio is quite low, meaning the heap can get really quite empty before it shrinks. To encourage it to shrink earlier, raise the value.
Note, however, that there is a performance cost to shrinking the heap. First, it takes some time actually to change the heap size. Second, making Java run with little headroom will mean more GC runs, which will cost performance.
In summary, these settings should allow you to get what you want, but do take care, and measure the real performance of your app in real situations.
Betty Rubble? Well, I would go with Betty... but I'd be thinking of Wilma.
Joined: Jan 31, 2006
Thanks very much Peter, certainly gave me a starting point.
I also found this article, which seems to contradict you slightly, unless I'm mis-reading it...
The way I read it, it's saying that if I reduce both MinHeapFreeRatio and MaxHeapFreeRatio, the heap will be more inclined to shrink. Let me know if you disagree.
Regardless though, I played around with the numbers a fair bit, and, with Windows Task Manager open, I never see the memory allocated to Java shrink. It increases as I work, and even if I force a garbage collection, the allocation remains the same. I can see that Java isn't using all of that memory, because after a garbage collect, the amount of memory allocated remains constant for a while, before it increases, presumably because Java's got some space in the heap.
My question is - am I wrong in expecting the allocation in Task Manager to drop? Will Windows always allocate that space to Java, regardless of whether or not Java wants it? (If I minimise my application, the memory allocation drops right down, and essentially starts again from low values when I restore/maximise the window).
Joined: Oct 30, 2001
I made a mistake in my original post - I should have gone to look at my code, which is correct. Anyway, the article is right: low values make it keener to shrink the heap.
Which column are you looking at in Windows Task Manager? If you are looking at the Mem Usage column, that is the *wrong* column. It shows physical memory use, which is not under your control at all and is confusing. You need to look at the VM Size column, which is not displayed by default, but will be displayed if you turn it on.
Better, use one of Java's monitoring applications, like jconsole, to view the heap expanding and contracting.
Joined: Jan 31, 2006
Thanks very much, Peter. Great help - things don't look quite so bad!
I didn't know about JConsole - for anyone reading this who's interested, and as ignorant as me, I found this page useful: