I have multiple servers running CentOS 5.4 and only one application running on Java VM. I've configured the Java VM with the following arguments:
java -Xmx4500M -server -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode -XX:NewSize=1024m -Djava.net.preferIPv4Stack=true -Dcom.sun.management.jmxremote=true
The machines I'm running the VM on has 6 GB RAM and no other applications running. After a while, the java process starts to hit the swap space really hard, I get this info out of the top
command:
7658 root 25 0 11.7g 3.9g 4796 S 39.4 67.3 543:54.17 java
On the other hand, if I connect via JConsole, it reports the Java VM has 2.6 GB used, 4.6 GB commited and 4.6 Gb max.
java -version returns:
java version "1.6.0_17"
Java(TM) SE Runtime Environment (build 1.6.0_17-b04)
Java HotSpot(TM) 64-Bit Server VM (build 14.3-b01, mixed mode)
Why is the Java VM expanding so much past it's allocated heap size? And where does that memory go, if it's not reported in JConsole?
-Xmx is the maximum amount of heap space being used by the vm. It does not include memory for the classes loaded, the vm itself or stacks of threads or the memory used for the JIT for instance. The line from top is also misleading since the first number included shared memory that's used by other programs as well. The second nummer 3.9g is the resident size and closer to reality.
My recommendation: Check if you really need that much heap (number and size of objects) and reduce the -Xmx number if you can.
I have noticed a bug in some commercial Java based applications, where the application is well behaved in 32bit Java but requires an extra (and mostly unnecessary) 1.25GB just to get started on 64bit Java. So what takes 256MB in 32bit Java takes 1.5GB on a 64bit runtime.
I suspect that Java is reporting what it thinks the application is using, but not its own runtime overhead, particularly in the case where this bug is invoked.
You could try running the app on a 32 bit runtime, or going back to the vendor's tech support (may cost $$) and asking what's up.
Ultimately, if you succeed in limiting total memory footprint, you just force the app to crash sooner, and you are still left with a problem.