The question is not about the maximum heap size on a 32-bit OS, given that 32-bit OSes have a maximum addressable memory size of 4GB, and that the JVM\'s max heap size depen
You can ask the Java Runtime:
public class MaxMemory {
public static void main(String[] args) {
Runtime rt = Runtime.getRuntime();
long totalMem = rt.totalMemory();
long maxMem = rt.maxMemory();
long freeMem = rt.freeMemory();
double megs = 1048576.0;
System.out.println ("Total Memory: " + totalMem + " (" + (totalMem/megs) + " MiB)");
System.out.println ("Max Memory: " + maxMem + " (" + (maxMem/megs) + " MiB)");
System.out.println ("Free Memory: " + freeMem + " (" + (freeMem/megs) + " MiB)");
}
}
This will report the "Max Memory" based upon default heap allocation. So you still would need to play with -Xmx
(on HotSpot). I found that running on Windows 7 Enterprise 64-bit, my 32-bit HotSpot JVM can allocate up to 1577MiB:
[C:scratch]> java -Xmx1600M MaxMemory Error occurred during initialization of VM Could not reserve enough space for object heap Could not create the Java virtual machine. [C:scratch]> java -Xmx1590M MaxMemory Total Memory: 2031616 (1.9375 MiB) Max Memory: 1654456320 (1577.8125 MiB) Free Memory: 1840872 (1.75559234619 MiB) [C:scratch]>
Whereas with a 64-bit JVM on the same OS, of course it's much higher (about 3TiB)
[C:scratch]> java -Xmx3560G MaxMemory Error occurred during initialization of VM Could not reserve enough space for object heap [C:scratch]> java -Xmx3550G MaxMemory Total Memory: 94240768 (89.875 MiB) Max Memory: 3388252028928 (3184151.84297 MiB) Free Memory: 93747752 (89.4048233032 MiB) [C:scratch]>
As others have already mentioned, it depends on the OS.
For a 64-bit host OS, if the JVM is 32-bit, it'll still depend, most likely like above as demonstrated.
-- UPDATE 20110905: I just wanted to point out some other observations / details:
Runtime.MaxMemory
that can be allocated also depends on the operating system's working set. I once ran this while I also had VirtualBox running and found I could not successfully start the HotSpot JVM with -Xmx1590M
and had to go smaller. This also implies that you may get more than 1590M depending upon your working set size at the time (though I still maintain it'll be under 2GiB for 32-bit because of Windows' design)one more point here for hotspot 32-bit JVM:- the native heap capacity = 4 Gig – Java Heap - PermGen;
It can get especially tricky for 32-bit JVM since the Java Heap and native Heap are in a race. The bigger your Java Heap, the smaller the native Heap. Attempting to setup a large Heap for a 32-bit VM e.g .2.5 GB+ increases risk of native OutOfMemoryError depending of your application(s) footprint, number of Threads etc.
I have tried setting the heap size upto 2200M on 32bit Linux machine and JVM worked fine. The JVM didnt start when I set it to 2300M.
As to why a 32-bit JVM is used instead of a 64-bit one, the reason is not technical but rather administrative/bureaucratic ...
When I was working for BEA, we found that the average application actually ran slower in a 64-bit JVM, then it did when running in a 32-bit JVM. In some cases, the performance hit was as high as 25% slower. So, unless your application really needs all that extra memory, you were better off setting up more 32-bit servers.
As I recall, the three most common technical justifications for using a 64-bit that BEA professional services personnel ran into were:
.
The limitation also comes from the fact that for a 32 bit
VM, the heap
itself has to start at address zero if you want all those 4GB
.
Think about it, if you want to reference something via:
0000....0001
i.e.: a reference that has this particular bits representation, it means you are trying to access the very first memory from the heap. For that to be possible, the heap has to start at address zero. But that never happens, it starts at some offset from zero:
| .... .... {heap_start .... heap_end} ... |
--> (this can't be referenced) <--
Because heap never starts from address zero in an OS
, there are quite a few bits that are never used from a 32
bits reference, and as such the heap that can be referenced is lower.
We recently had some experience with this. We have ported from Solaris (x86-64 Version 5.10) to Linux (RedHat x86-64) recently and have realized that we have less memory available for a 32 bit JVM process on Linux than Solaris.
For Solaris this almost comes around to 4GB (http://www.oracle.com/technetwork/java/hotspotfaq-138619.html#gc_heap_32bit).
We ran our app with -Xms2560m -Xmx2560m -XX:MaxPermSize=512m -XX:PermSize=512m with no issues on Solaris for past couple of years. Tried to move it to linux and we had issues with random out of memory errors on start up. We could only get it to consistently start up on -Xms2300 -Xmx2300. Then we were advised of this by support.
A 32 bit process on Linux has a maximum addressable address space of 3gb (3072mb) whereas on Solaris it is the full 4gb (4096mb).