- Does your Java process using Sun JRE fails with -Xmx1200m on Windows 32-bit OS but you want more ? Here is some explaination on why it happens and how to fix it.
32-bit Windows by-default provides 2 GB of Virtual Address Space for each process; this is independent of the physical RAM in the system. When a process starts executing it loads process binary and other resources like DLLs at different addresses within the 2 GB Virtual Address Space.
Sun JVM Heap requires that a contiguous block of Virtual Address space be reserved (I guess it is for some GC optimizations) and the size of this contiguous block depends on other resources loaded by the JVM.
Following screen-shot of Process Explorer for a simple Java process helps in explaining this concept better. A Java process is run with following command-line
java -Xshare:on -Xmx500m MemTest
Now we search for big contiguous chunks of memory and find two of them between
a) java.exe(0x400000) and classes.jsa (0x2AB80000) = 679 MB
b) classes.jsa(0x2C03B000) and lpk.dll(0x629C0000) = 873 MB
From these figures we see that if sharing mode is ON, it bisects the contiguous memory, greatly reducing the max heap size. If I modify the command-line to use -Xmx900m, the process will fail to start.
DLLs should also be watched out for such issues. From my experience some of the DLLs from older service packs from Microsoft would load around 0x4000000, which reduced the max heap size possible.
Lastly, if your Java application is deployed at customer-site, then some apps like anti-virus, etc tend to inject their DLLs in every running process. They can also cause such issue.
What to do for fixing this up
a) use -Xshare:off (sharing can be ON by default, so add this explicitly)
b) if some DLL is loading after 0x400000 but before 0x6000000, find a work-around for it (some missing hotfix, rebase DLL, etc)
External Resources:
