Share and Enjoy: Memory Usage of Multiple Java Processes on Windows

So you're running a few Java applications on Windows and want to know the total resident memory footprint. Simple - just sum up the Task Manager Mem Usage numbers for all java[w].exe images, right? Well, no. Believe it or not, adding up the Mem Usage to determine total memory usage of a set of processes will almost always give you the wrong answer.

The reason is that the Mem Usage accounting charges each process for memory that is shared with other processes. For example, although there's only one copy in physical memory, DLL read-only memory usage is charged against every process that has loaded a particular DLL.

We can't fault Task Manager for this, because the measurement is accurate from the perspective of a single process. But not when considering the actual cost of multiple processes.

So how do we get the right number? The answer is to subtract out all shared memory that's counted more than once. Although Task Manager doesn't provide an easy way to do this, there's a tool called vadump.exe that does precisely what we want.

With the "-o" (dump current working set) and "-s" (summary info only) options, vadump displays working set information for a single process. Here is the output for a typical medium-sized graphical Java application. (Some output is omitted for the sake of clarity.)

Category                        Total        Private Shareable    Shared
                           Pages    KBytes    KBytes    KBytes    KBytes

Grand Total Working Set     8841     35364     23940      8964      2460
"Total KBytes" corresponds exactly with the Task Manager Mem Usage column. But now we have additional information as well. "Shareable KBytes" is memory that is potentially shareable but is not currently shared, because only this process is using it. "Shared KBytes" is memory that is actually shared with one or more other processes.

In this example, not much is shared because we're only running one Java process. When another instance of the same application is launched, the vadump output becomes:

Category                        Total        Private Shareable    Shared
                           Pages    KBytes    KBytes    KBytes    KBytes

Grand Total Working Set     8841     35364     23908        92     11364
Since two copies of the same Java application are running, almost all the shareable memory is in fact shared.

So let's figure out the total footprint using both methods. First, using the method we know to be incorrect, summing up Task Manager's Mem Usage numbers gives us just over 69M as the combined footprint. Now let's calculate the actual resident set footprint of these two processes.

To calculate the true footprint, we simply subtract out the shared charge for instances beyond the first. For n instances of the same application, the formula looks like this:

True Footprint = (Mem Usage \* n) - (Shared Kbytes \* (n - 1))
For the two application instances in this example, the true working set footprint is just under 58M. That's a significant difference - if we didn't consider shared memory, the footprint estimate is off by almost 20%! And the error rate only increases as you add additional instances.

It's also important to realize that even though our example uses two copies of the same application, the footprint analysis translates very well to different Java apps. For example, when running two different medium-sized graphical Java applications, the Shared KBytes for each are 11084 and 11076 - almost as good as the example above. This rule of thumb holds up for most Java programs. To confirm it, you can look at the vadump verbose output and verify at a per-DLL level precisely what is being shared between the Java processes.

Where exactly does the sharing come from? Two places, mostly. The first is shareable DLLs regions such as the text section. The second is from the class data sharing feature, which shares read-only class metadata between processes. For typical applications, each of these contributes roughly equally to the total amount of shareable memory.

So this entry tries to demonstrate that the multiprocess Java memory usage situation on Windows may be better than you think. If it's still not good enough, you might check out Chris Oliver's JApplication, which uses classloader-based isolation to host multiple (well-behaved) applications in a single JVM instance.

Another good reference for those interested in multiprocess JVM footprint is Dave Dice's MVM blog entry.


[Trackback] MVM -- the Multi-Tasking Virtual Machine technology developed by SunLabs -- is extremely useful in some environments. There's considerable debate, however, about why MVM is not part of J2SE. For balanced background reading I'd recommend starting with...

Posted by David Dice's Weblog on January 12, 2007 at 03:48 AM EST #

Hi Steve, I wasn't aware that you too blogged. (Or is this your first post?) Considering the immense amount of help you provided in explaining hotspot's memory usage on Solaris, I look forward to many insightful posts from you on related topics. Thanks.

Posted by Bharath Ravi Kumar on January 18, 2007 at 05:57 PM EST #

Bharath, I didn't know you blogged either. Yes, this is my first post. Thanks for stopping by and for the kind words! Stay tuned for a class data sharing entry coming soon....

Posted by Steve Bohne on January 19, 2007 at 01:47 AM EST #

I have been seeing quite a few blogs about CDS and the upcoming plans for a MVM. As a temporary solution, could you just set up a miniature java app server, and instead of saying java foo, say javaa foo, and it runs the code in a new thread (possibly starting up the mini-app if not yet started, but then keeping it running?) Or javaa foo a and javaa foo2 b would start up 2 listening jvms, a and b, and run foo and foo2?

Posted by James on February 21, 2007 at 04:15 PM EST #

You mention vadump.exe . This appears to be a tool that is a part of the windows 2000 resource kit. Does anyone know of a Windows XP counter-part for this tool?

Posted by Larry W. Virden on February 22, 2007 at 12:32 AM EST #

Do you know how i can, in JAVA, run only my process continuously?

Posted by 1/2Kg de Broa on March 03, 2008 at 03:24 AM EST #


Posted by Erdoğan_ipek on April 13, 2008 at 03:23 AM EDT #

Post a Comment:
  • HTML Syntax: NOT allowed



« February 2017