A simple "Hello World" needs 10G virtual memory on a 64-bit machine vs 1G at 32-bit?

JavaMemory ManagementJvm64 BitVirtual Memory

Java Problem Overview


Running a simple Java program on our production machine, I noticed that this program eats up more 10G virt. I know that virtual memory is not that relevant, but at least I would like to understand why this is needed.

public class Main {
  public static void main(String[] args) {
        System.out.println("Hello World!");
        try {
                Thread.sleep(10000);
        } catch(InterruptedException e) {
                /* ignored */
        }
  }
}

Heres what top is saying when i run that little program:

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
18764 myuser    20   0 10.2g  20m 8128 S  1.7  0.1   0:00.05 java

Does anyone know why this is happening?

uname -a says:

Linux m4fxhpsrm1dg 2.6.32-358.18.1.el6.x86_64 #1 SMP Fri Aug 2 17:04:38 EDT 2013 x86_64 x86_64 x86_64 GNU/Linux

On an older 32bit-linux machine the same program consumes only about 1G virt. The old machine has 4GB RAM, the new one 32GB.

Java Solutions


Solution 1 - Java

The default sizes for initial heap and maximum heap are defined as a percentage of the machine's physical memory, of which a production server nowadays tends to have a whole lot.

You can choose both via the -Xms and -Xmx command line options.

Solution 2 - Java

Virtual memory really doesn't matter to you.

The basic difference between 32-bit and 64-bit is that the address space in 64-bit is incredibly large. If 10 GiB looks like a lot to you, note that .NET on 64-bit can use TiBs of memory like this. Yet on 32-bit, .NET is much more conservative (and so is JVM) - the address space is 4 GiB total - that's not a lot.

But it's irrelevant - it doesn't matter. It's just a thing that greatly simplifies programming, and has no negative effect on the host OS whatsoever. It creates a continuous address space for the VM to use, which means that you don't have to fragment the heap (or worse, the stack, where it's more or less impossible - but those tend to be only a MiB or so) as you get to require more "real" memory. When you finally commit the virtual memory, it becomes slightly more real - at that point, it more or less has to be backed by some data storage - be it the page (swap) file or physical RAM.

The point is, the physical location of the memory isn't necessarily continuous, but that's done outside of your reach, and the mapping is generally very fast. On the other hand, having to, say, index an array, that's actually fragmented over 10 different virtual address memory blocks, that's (completely unnecessary) work.

So there you have it - virtual memory is almost free on 64-bit. The basic approach is "if it's there, use it". You're not limiting the other applications, and it saves you quite a bit of work if you do actually end up using it. But until that point comes, you've only got a reservation. It doesn't translate to any physical memory at all. You don't pay for the friends that might come tonight and sit at your table, but you still have the space for them to sit if they do come - and only when they finally come do you actually get "charged".

See this question for more information about the way Java behaves on different machines and with different versions: https://stackoverflow.com/questions/2915276/what-is-the-default-maximum-heap-size-for-suns-jvm-from-java-se-6 The maximum heap size also determines the amount of virtual memory reserved, because the heap has to be a continuous address space. If it weren't pre-reserved, it could happen that the heap could not expand to this maximum value, because someone else reserved a region of address space in the place the heap has to expand.

Solution 3 - Java

It turns out that on a modern computer architecture that uses virtual memory addressing (where the "memory space" an application sees does not actually relate to memory that's actually physically allocated), it really doesn't matter how much of this virtual "memory space" is given to an application upon startup. It doesn't mean that this much memory has been allocated by the system.

If an application sees a virtual address space 10GB large all it signals to the app is that it may use memory addresses up to 10GB if it wants. However, memory is not actually allocated in physical RAM until it is actually written to, and this is done on a page-by-page basis, where a page is a 4kB section of memory. The virtual address space, is just that - completely virtual until actually used.

Let's say an application is given 10GB of address space and it starts using some of it. As a "fresh" - previously untouched - page of this virtual memory is first written to, the system will, on a low level, "map" this virtual page to a section of physical memory, then write it. But that application itself does not have to worry about such details, it just acts as if it has full access to a virtual area of memory.

In the case of Java applications, it's not the application itself but Java that is allocated that address space, and Java simply requests a huge address space by default - the amount it requests is calculated relative to the physical memory size, but not because it has any need to be conservative, but just for practicality - an application is probably not going to want enough heap size to totally bring a server to its knees, so it's operating on the assumption it won't. As I said above this does not mean that this much is "allocated" or that the system has had to expend many resources doing so.

Solution 4 - Java

It's not your program using up that memory, it's the Java VM reserving that memory, regardless of which program is loaded.

Solution 5 - Java

Imagine you're in the document storage business. You have a small facility in the middle of the city that stores boxes of papers, and a much larger warehouse outside of town with 1000 times the space. Every box has a label on it identifying its contents.

The in-city facility is main memory. The warehouse is disk space.

A 10GB virtual memory allocation for a new process doesn't mean finding room for 10 billion boxes for a new customer. It means printing 10 billion labels for boxes with contiguous ID numbers on them.

Solution 6 - Java

This is not the amount of physical memory the application is actually using. A virtual memory used by all processes can be orders of magnitude more than the amount of physical RAM on the machine, without any obvious problems.

Solution 7 - Java

Your program is NOT using so much memory. JVM / OS is reserving that memory i.e, the limit UPTO WHICH your program can use. Also, like one of the answer clearly mentions. 32 bit and 64 bit have got nothing to do with this. 32 bit means you can access upto 2^32 physical memory locations. and 64 bit means upto 2^64.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser3246431View Question on Stackoverflow
Solution 1 - JavaMichael BorgwardtView Answer on Stackoverflow
Solution 2 - JavaLuaanView Answer on Stackoverflow
Solution 3 - JavathomasrutterView Answer on Stackoverflow
Solution 4 - JavaPieter BView Answer on Stackoverflow
Solution 5 - JavaRussell BorogoveView Answer on Stackoverflow
Solution 6 - JavaAudrius MeškauskasView Answer on Stackoverflow
Solution 7 - JavaTheLostMindView Answer on Stackoverflow