I want to chose a value for maximum JVM heap size. I have some questions about it.
1) Is it usually related with the available physical memory size on the system? If so, is there any formula about this?
2) For the 32-bit JVM, can I set a value larger than 4GB even if the physical memory is very large?
3) Do I need to consider some impact of OS (e.g. Windows, Linux)?
Thanks
1.) Yes amount of memory you can allocate to JVM is related to physical memory available on your system. There is no fixed formula, however there is a rule of thumb that you can use to decide the memory allocation size for your process. There is memory recommendation for different Operating Systems. So (PhysicalMemory - Recommended OS memory) can be allocated to the java process. It varies for 32-bit vs 64-bit OS. If you don't have any other process then this formula will work fine. However if you have other memory consuming processes then you need to take into account memory allocation of those processes as well.
e.g. Windows 7 has following recommended requirement 1 gigabyte (GB) RAM (32-bit) or 2 GB RAM (64-bit). So, if you have 4GB physical memory then you can allocate 2GB to your process assuming 2 GB is used by OS.
2.) For 32-bit JVM you can not set the value larger than 4GB. In fact if your total physical memory is 4GB. You cannot allocate more than 2GB to your Java process. Checkout this answer for more detailed explanation
3.) Yes you should consider OS impact. Check the recommended memory configuration for different Operations Systems and decide memory for your Java process.
Hope this helps.
Related
Imagine I have a 64-bit machine with the total amount of memory (physical + virtual) equal to 6 GB. Now, what will happen when I run 5 applications with -Xmx2048m at the same time? They won't fail on start since this is 64-bit OS but what will happen when they all will need to use the 2GB of memory which I've set for them?
Question: Is it possible that there will be some memory leaks or something? What will happen? What are possible consequences of doing that?
I've read those questions: this and this, but they don't actually answer my question since I want to run more than one application which doesn't exceed the limit of memory on its own, but all together they do.
What you will experience is increased swapping during major garbage collections and thus increased GC pause-times.
When used memory exceeds physical memory (well, in fact even before that) modern OSs will write some of the less-used memory to disk. With a JVM this will most probably be some parts of the heap's tenured generation. When a major GC occurs it will have to touch all of the heap so it has to swap back in all of the pages it has offloaded to disk resulting in heavy IO-activity and increased CPU-load.
With multiple JVMs that have few major GCs this might work out with slightly increased pause times since one JVM's heap should easily fit into physical memory, but with one JVM's heap exceeding physical memory or simultaneous major GCs from several JVMs this might result in lots of swapping in and out of memory-pages ("thrashing") and GCs might take a really loooong time (up to several minutes).
Xmx merely reserves virtual address space. And it is virtual not physic.
The response of this setting depends on the OS :
Windows : The limit is defined by swap + physical. The exception are large pages (which need to be enabled with a group policy setting), which will limit it by physical ram (XMS is not possible).
Linux behavior is more complicated. (it depends on the vm.overcommit_memory and related sysctls and various flags from the mmap syscall) can (but not all) be controlled by JVM configuration flags. The behavior can be :
- Xms can exceed total ram + swap
- Xmx is capped by available physical ram.
I have set the default memory limit of Java Virtual Machine while running Java Application like this...
java -mx128m ClassName
I Know this will set maximum memory allocation pool to 128MB, but I don't know what the benefit is, of specifying this memory limit of JVM?
Please enlighten me in this issue...
On Sun's 1.6 JVM, on a server-class machine (meaning one with 2 CPUs and at least 2GB of physical memory) the default maximum heap size is the smaller of 1/4th of the physical memory or 1GB. Using -Xmx lets you change that.
Why would you want to limit the amount of memory Java uses? Two reasons.
Firstly, Java's automatic memory management tends to grab as much memory from the operating system as possible, and then manage it for the benefit of the program. If you are running other programs on the same machine as your Java program, then it will grab more than its fair share of memory, putting pressure on them. If you are running multiple copies of your Java program, they will compete with each other, and you may end up with some instances being starved of memory. Putting a cap on the heap size lets you manage this - if you have 32 GB of RAM, and are running four processes, you can limit each heap to about 8 GB (a bit less would be better), and be confident they will all get the right amount of memory.
Secondly (another aspect of the first, really), if a process grabs more memory than the operating system can supply from physical memory, it uses virtual memory, which gets paged out to disk. This is very slow. Java can reduce its memory usage by making its garbage collector work harder. This is also slow - but not as slow as going to disk. So, you can limit the heap size to avoid the Java process being paged, and so improve performance.
There will be a default heap size limit defined for the JVM. This setting lets you override it, usually so that you can specify that you want more memory to be allocated to the java process.
This sets the maximum Heap Size. The total VM might be larger
There is always a limit because this parameter has a default value (at least for the Oracle/Sun VM)
So the benefit might either be: you can give the memory to the app that it actually needs in order to work (efficiently) or if you come from the other direction: (somewhat) limit the maximum memory used in order to manage the distribution of resources among different applications on one machine.
There already has been a question about java and memory SO: Java memory explained
A very nice article about Java memory is found here. It gives an overview of the memory, how it is used, how it is cleaned and how it can be measured.
The defaults of the memory are (prior java 6):
-Xms size in bytes Sets the initial size of the Java heap. The
default size is 2097152 (2MB). The values must be a multiple of, and
greater than, 1024 bytes (1KB). (The -server flag increases the
default size to 32M.)
-Xmn size in bytes Sets the initial Java heap size for the Eden
generation. The default value is 640K. (The -server flag increases
the default size to 2M.)
-Xmx size in bytes Sets the maximum size to which the Java heap can
grow. The default size is 64M. (The -server flag increases the
default size to 128M.) The maximum heap limit is about 2 GB (2048MB).
Another source (here) states that in Java 6 the default heap size depends on the amount of system memory.
I assume this should help avoid high memory consumption (due to bugs or due to many allocations and deallocations). You would use this if you design for a low-memory system (such as an old computer with little amounts of RAM, mobile phones, etc.).
Alternatively, use this to increase the default memory limit, if it is not enough for you and you are getting OutOfMemoryExceptions for normal behavior.
I am using 32 bit win.7 and using Eclipse. Also having 4GB RAM.
I want to allocate my java application a maximum heapsize of around 3 GB, but I am able to allocate maximum 1.5GB through VM arguments -Xmx1056m.
What should I do? If I Install a 64 bit win.7. it would be able then to allocate 3GB heapsize to my app?
A regular 32-bit Windows process can only address 2GB of memory, even if you have more memory available. You can find the memory limits for different Windows versions here.
Since the VM need memory for more things than just the heap, the max heap size will be slightly less than the maxmimum memory available to the process. Usually, you can tweak the heap up to around 1.6GB for a 32-bit Windows VM.
You need a 64bit OS and 64bit VM to allocate this much RAM.
I don't have the link right now that describes the JVM memory management process. The limitation you have stumbled upon is a limitation of how Java performs garbage collection. The Java memory heap must be a contigious block. The garbage collection algorithms were optimized for this design limitation so they can perform efficiently. In a 32bit operating system, you are not in control of what memory addresses device drivers are loaded into. On Windows, the OS will only reallocate the device driver base address stored in the DLL if it conflicts with an already loaded code. Other operating systems may reallocate all device drivers on load so they live in a contiguous block near the kernel.
Basically, the limitation is the same for 64bit and 32bit operating systems. It's just on a 64bit OS there are several more address ranges to choose from. Make sure you use a 64bit JVM to match the OS. That's why the 64bit OS is able to find a larger contigious block of memory addresses than the 32bit OS.
EDIT: Additionally the 32bit JVM has a max heap size limit of 2GB.
REFERENCE:
http://publib.boulder.ibm.com/infocenter/javasdk/tools/index.jsp?topic=/com.ibm.java.doc.igaa/_1vg00014884d287-11c3fb28dae-7ff6_1001.html
Java maximum memory on Windows XP
http://forums.sun.com/thread.jspa?messageID=2715152#2715152
What you will need is not only a 64bit OS and a 64bit VM, but also more memory.
On a 32bits Windows system the virtual address space is split with 2 GB for kernel operations and 2 GB for user applications. So you're screwed.
There's one possible but very unlikely workaround: you can enable the /3GB switch to raise this limitation and have the system allocate 1GB of virtual address space for for kernel operations and 3GB for user applications (if they are /LARGEADDRESSPACEAWARE).
Unfortunately, the 32bits Sun/Oracle HotSpot JVM isn't LARGEADDRESSAWARE (that I know of), and other 32bits JVM likely aren't either.
But think about it: even if you were able to do that, you would use all the memory available for you system. Nothing would be left for other programs after you've allocated your 3GB of heap for your JVM. Your system would be swapping to disk all the time. It would be unusable.
Just get a 64bis OS with more RAM. That's all there is for you, short of finding ways to have your program use less memory.
On a 64-bit Windows machine with 12GB of RAM and 33GB of Virtual Memory (per Task Manager), I'm able to run Java (1.6.0_03-b05) with an impossible -Xmx setting of 3.5TB but it fails with 35TB. What's the logic behind when it works and when it fails? The error at 35TB seems to imply that it's trying to reserve space at startup. Why would it do that for -Xmx (as opposed to -Xms)?
C:\temp>java -Xmx3500g ostest
os.arch=amd64
13781729280 Bytes RAM
C:\temp>java -Xmx35000g ostest
Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.
On Solaris (4GB RAM, Java 1.5.0_16), I pretty much gave up at 1 PB on how high I can set -Xmx. I don't understand the logic for when it will error out on the -Xmx setting.
devsun1.mgo:/export/home/mgo> java -d64 -Xmx1000000g ostest
os.arch=sparcv9
4294967296 Bytes RAM
At least with the Sun 64-bit VM 1.6.0_17 for Windows, ObjectStartArray::initialize will allocate 1 byte for each 512 bytes of heap on VM startup. Starting the VM with 35TB heap will cause the VM to allocate 70GB immediately and hence fail on your system.
The 32-bit VM (and so I suppose the 64-bit VM) from Sun does not take account for available physical memory when calculating the maximum heap, but is only limited by the 2GB addressable memory on Windows and Linux or 4GB on Solaris or possibly failing to allocate enough memory at startup for the management area.
If you think about it, checking the sanity of the max heap value against available physical memory does not make much sense. X GB of physical memory does not mean that X GB is available to the VM when required, it can just as well have been used by other processes, so the VM needs a way to cope with the situation that more heap is required than available from the OS anyway. If the VM is not broken, OutOfMemoryErrors are thrown if memory cannot be allocated from the OS, just as if the max heap size has been reached.
According to this thread on Sun's java forums (the OP has 16GB of physical memory):
You could specify -Xmx20g, but if the total of the memory needed by all the processes on your machine ever exceeds the physical memory on your machine, you are likely to end up paging. Some applications can survive running in paged memory, but the JVM isn't one of them. Your code might run okay, but, for example, garbage collections will be abysmally slow.
UPDATE: I googled a bit further and, according to the Frequently Asked Questions About the Java HotSpot VM and more precisely How large a heap can I create using a 64-bit VM?
How large a heap can I create using a 64-bit VM?
On 64-bit VMs, you have 64 bits of
addressability to work with resulting
in a maximum Java heap size limited
only by the amount of physical memory
and swap space your system provides.
See also Why can't I get a larger
heap with the 32-bit JVM?
I don't know why you are able to start a JVM with a heap >45GB. This is a bit confusing...
Just to re-enforce Pascal's answer--Be very careful in windows when specifying a high max memory size. I was working on a server project that required as much physical memory as possible, but once you are over physical ram, abysmal performance is not a good description of what happens--Hung machine might be better.
What happens (at least this is my evaluation of it after days of examining logs and re-running tests) is, Windows runs out of ram and asks all apps to free up what they can. When it asks Java, Java kicks off a GC. The GC touches all of memory (causing anything that has been swapped out to be swapped in). This in turn causes windows to run out of memory. Windows then sends a message to all apps asking them to free up what they can.... (recurse indefinitely)
This may not ACTUALLY be what is going on, but the fact that Java GC touches Very Old Memory at times makes it incompatible with paging.
What's the maximum amount of heap space that one can allocate for java on a 64-bit platform? Is it unlimited?
Theoretically 264, but there might be limitations (obviously)
According to this FAQ it's only limited by memory and swap space on the local system:On 64-bit VMs, you have 64 bits of addressability to work with resulting in a maximum Java heap size limited only by the amount of physical memory and swap space your system provides.
See also Why can't I get a larger heap with the 32-bit JVM?
Also keep in mind you need to set the max heap via command line. Without an -Xmx command. without it Java uses 64mb + 30% = 83.2mb as a default max heap on 64 bit machines according the same FAQ.
java -Xmx1000g myClass
works fine on my machine. But it dosn't seem to yet support the 't' modifier so you can't specify max memory in terabytes yet :)
If you could make every atom in the universe into a byte of RAM, you could allocate it in a 64 bit address space.
Actually, that's a slight exaggeration.
There are 10^80 atoms in the universe (according to WolframAlpha), and 2^64 bytes of address space in a 64 bit system, so you'd only be able to address 1 out of every 5x10^60 atoms. But if you have 18 qintillion bytes of RAM, you'd probably need a couple of quantum black holes to power it with.
This probably depends on the system your VM is running in. If you are running a AMD x64 architecture the address space of currently shipped processors uses 48 Bits, not 64. This results in a theoretical maximum of roughly 256 TB. (See http://en.wikipedia.org/wiki/X86-64)
I am not a specialist in VMs, but any modern OS typically will give as much memory as there is physical RAM plus available virtual memory. Probably thats what the VM will pass to your application depending on its configuration.
With recent VMs from Sun, the practical heap limit size is usually 512 times the available physical and/or virtual memory. Even if the theoretical limit is much higher, the VM will allocate 1 byte for maangement purposes for each 512 bytes of heap memory on startup, so 1TB of heap will immediately require 2GB for the memory management.
In theory its between 2^63 and 2^64 bytes.
In practice it is limited by the amount of physical memory and swap space available on your machine. And the physical memory is in turn limited by your chipset (i.e. the number of address pins on the physical memory address bus) and motherboard (i.e. the number and size of the DIMM sockets).