UPDATE: 20081104 — More recent info?
I notice this page gets a lot of hits still. It’s quite old and I haven’t researched to see what is happening in OpenJDK or to see if 6u10 adresses any of this for Windows. If anyone has more info please comment or write to me, I’d like to update what I have.
—
On the 32-bit Windows platform, JVM programs can only ever use up to about 1.5–1.6 GiB of memory in RAM per Java VM process. Allocating a heap size greater than this amount will either not work, or force paging and poor performance.
From my own research on this issue (and taking into account Microsoft’s advice on KnowledgeBase about Win32 virtual memory allocation), this is what I understand about the limits of RAM usability, both for Win32 itself, and for 32-bit JVMs running on Windows. I haven’t researched if this limit applies for 64-bit Windows or JVMs, nor what Vista might be doing. Also, though the 4GiB limit is inherent to 32-bit machines, the 2GiB limit seems to be peculiar to Windows, and I’ve not seen it anywhere in Linux, Solaris or BSD: when unix runs on a 32-bit machine, there’s a 4GiB limit, but not 2GiB.
Any 32-bit binary processor has a hard limit of 4,294,967,296 which is the largest number that can be represented in a single 32 bit machine word: 232 = 4,294,967,296. On a byte-addressed computer like Intel IA32, that equates 4294967296 bytes = 4194304 KiB = 4096 MiB = 4GiB.
Normal memory access techniques used by 32-bit Windows programs use standard linear byte addressing, and so are limited to 4GiB of addressable memory, whether it is real or virtual.
On Windows, the amount of this 4GiB space that can actually occupy physical RAM is halved to 2GiB per process. Windows uses the other 2GiB of virutal address space as a per-process overhead for the kernel, and to speed up paging. This is really dumb because it means that if your process allocates > 2GiB heap memory, then Windows must page some to virtual memory, even if you have > 2GiB of actual RAM! Sort of like the DOS 640KiB limit reborn!
To overcome this dumb design, Windows has a memory addressing scheme called the AWE API, which allows a process to allocate up to 3GiB of memory and have that memory reside on chips. To use this, the program must be specially written to use the AWE API.
There’s also another virtual memory technology in Windows called PAE. This is not useful to application programs — it is how the Windows kernel can use > 4GiB of real memory to allocate physical memory to all processes on the system. Each process is still limited to the 4GiB address space each, with 2GiB mapped to RAM (or 3GiB, if the program uses the AWE API) and the rest having to be virtual (paged to disc). PAE just lets Windows keep more than one of these big processes in memory at once even if their combined total heap is more than 4GiB (and assuming you have more than 4GiB of RAM of course).
Both Sun and BAE have refused to use the AWE API for implementing their Java VMs. This is probably because the AWE API does not allow for a contiguous address space of 3GiB, but rather breaks it at the 2GiB mark. The Java VM spec’ used to require a contiguous addressed heap (though this has changed for the JVMS 2nd Ed.…). So any Java VM running on Windows is still limited to at most < 2GiB per running program (actually, only about 1.5GiB is usable because of further overhead for the JVM itself). At least, so long as Win32 JVMs don’t use the AWE API. I’m not sure how difficult it would be for Sun or BAE to change their JVMs to make use of the AWE API in Windows, but the fact that they haven’t done so seems to indicate to me that it wouldn’t be easy. I have been unable to determine if IBM’s JVM uses it…
The only workable solution for utilizing greater than about 1.5–1.6 GiB per JVM process on a 32-bit host is to not run it in Windows (i.e. use Solaris, Linux or BSD). Real operating systems can let processes use 4GiB on 32-bit machines without special programming tricks. Or, you could switch to a 64-bit platform. Although there is a Windows for IA-64, I’m not sure about the availability of a 64-bit JVM for that platform.
It would be better to have a smaller heap on Win32, and if you need more, consider re-engineering the program to use less anyway. If your program is genuinely memory bound and you can’t get away from needing more than 1.5GiB heap, you could work around the Win32 memory limit by splitting your Java program into more than once process, each running on it’s own JVM, allocating 1.5GiB to each JVM, and then having the processes communicate with an IPC mechanism as needed, such as JMS. However there’s probably a lot more re-engineering work involved in this than there is to just migrate away from Win32 …
5 Comments
This is an impressive collection of complete factual errors.
Robert, please enlighten me. If you cannot show me where the errors are, then leave your troll bait elsewhere…
This page gets a high hit rate because it talks about java heap allocation and remote desktop. For some reason the amount of memory that Java can reserve when you are remoting in to XP is much more limited than if you are at the console. Even when you have loads of free memory.
E.g. I have a machine with 3 gig, task manager shows less than 1 Gig being used. ANT_OPTS -Xmx1024m -XX:MaxPermSize=512m
Ant -v from remote desktop causes a could not reserve enough heap error.
In console it works fine.
I just ran into this problem too. On a Windows Vista 32-bit system I can have Java use (with the -Xmx parameter) no more than exactly 1,665,135,275 bytes of memory.
On 32-bit NetBSD (Unix) I don’t have this problem, and I expect not to have it on 64-bit NetBSD either. I haven’t bothered to try Windows Vista 64-bit because there are too many drivers that simply aren’t available for it, and so it’s not an option — Unix meets all the needs anyway, so we’re just moving to NetBSD instead of investing any more time and money into trying to figure out how to make this work in Windows.
I just tried quickly on a system running Vista 64-bit with 8 GBs of RAM, and it seems that Windows Vista puts a hard limit of 3 GBs on application-based memory allocations.
Hmm, 3 GBs? That must be the magic number that Microsoft has been touting as a hardware limit (although we know that’s not true because Windows XP can see up to 4 GBs of RAM minus a few other things; under Xen in an HVM Guest on NetBSD I can get Windows XP Pro with SP3 to recognize 3.75 GBs of RAM without any problems).
This 1.5 GBs limit in 32-bit Windows, I wonder if it was merely doubled to 3.0 GBs in 64-bit Windows?
One Trackback/Pingback
[...] high-throughput event processing beyond what you can fit into a single machine’s (or JVM’s) memory [...]