Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 32bit Xmx vs java 64bit Xmx

Tags:

java

memory

jvm

I am really confused with this.

Xmx according to the java docs, is the maximum allowable heap size.
Xms is the minimum required java heap size, and is allocated at JVM start.

On a 32 bit JVM (4GB ram), java -Xmx1536M HelloWorld gives a cannot allocate enough memory error.
On a 64 bit JVM (4GB Ram), java -Xmx20G HelloWorld works just fine. But I don't even have that much virtual or physical memory allocated.

So from this, I conclude that Java 32 bit is allocating the 1536M at JVM startup, but Java 64 bit is not.

Why? A simple Hello World should not need 1536M to run. I am just specifying that 1536M is the maximum, not that it is needed.

Explanations anyone?

like image 609
user3219957 Avatar asked Jan 21 '14 15:01

user3219957


2 Answers

There is a distinction between allocating the memory and allocating the address space. The Oracle JVM is allocating the address space on startup to ensure the heap is contiguous. This allows for certain optimizations to be used with the heap.

If the allocation fails, then Java won't start... as you have seen. It isn't necessarily using that much memory, but it is allocating the required address space up-front. Since you are passing -Xmx1536m, it is saying ok, I need to allocate that in case you need it... and since it must be contiguous it does it up-front so it can guarantee it (or fails trying).

This behavior is the same on both 32-bit and 64-bit JVMs. What you are seeing is the 2GB per-process address space limitation of 32-bit processes (at least, on Windows this is the limitation - it may be slightly larger on other platforms) causing this allocation to fail on 32-bit, where 64-bit has no issues since it has much larger address space. But, you say, 1536m is less than 2GB, I should be good, right? Not quite - the heap is not the only thing being allocated in the address space, DLLs and other stuff is also allocated in the address space...so getting a contiguous 1536m chunk out of 2GB max on 32-bit is unfortunately very unlikely. I've seen values below 1000m fail on 32-bit processes with particularly bad fragmentation, and usually 1200-1300m is the max heap you can specify on 32-bit.

On modern OSes, ASLR (Address Space Layout Randomization) makes fragmentation of 32-bit process address space worse. It intentionally loads DLLs into random addresses for security reasons... making it even less likely you can get a big, contiguous heap in 32-bit.

In 64-bit, the address space is so large that fragmentation is no longer a problem and giant heaps can be allocated without issues. Even if you have 4GB of RAM on 32-bit, though, the 2GB per process address space limitation (at least on Windows) usually means the max heap is usually only 1300m or so.

like image 65
Joshua McKinnon Avatar answered Oct 12 '22 05:10

Joshua McKinnon


Actually, the application is not allocating the Xmx memory at startup.

The -Xms parameter configure the startup memory. (What are the Xms and Xmx parameters when starting JVMs?)

The 64bit environment allows a bigger memory allocation then 32bits. But, in fact, it's using the HD space, not the memory ram.

See this other post for more info.

Estimating maximum safe JVM heap size in 64-bit Java

like image 24
edubriguenti Avatar answered Oct 12 '22 06:10

edubriguenti