How is the default max Java heap size determined?

If I omit the -Xmxn option from the Java command line then a default value will be used. According to Java documentation

"the default value is chosen at runtime based on system configuration"

What system configuration settings influence the default value?


Solution 1:

On Windows, you can use the following command to find out the defaults on the system where your applications runs.

java -XX:+PrintFlagsFinal -version | findstr HeapSize

Look for the options MaxHeapSize (for -Xmx) and InitialHeapSize for -Xms.

On a Unix/Linux system, you can do

java -XX:+PrintFlagsFinal -version | grep HeapSize

I believe the resulting output is in bytes.

Solution 2:

For Java SE 5: According to Garbage Collector Ergonomics [Oracle]:

initial heap size:

Larger of 1/64th of the machine's physical memory on the machine or some reasonable minimum. Before J2SE 5.0, the default initial heap size was a reasonable minimum, which varies by platform. You can override this default using the -Xms command-line option.

maximum heap size:

Smaller of 1/4th of the physical memory or 1GB. Before J2SE 5.0, the default maximum heap size was 64MB. You can override this default using the -Xmx command-line option.

UPDATE:

As pointed out by Tom Anderson in his comment, the above is for server-class machines. From Ergonomics in the 5.0 JavaTM Virtual Machine:

In the J2SE platform version 5.0 a class of machine referred to as a server-class machine has been defined as a machine with

  • 2 or more physical processors
  • 2 or more Gbytes of physical memory

with the exception of 32 bit platforms running a version of the Windows operating system. On all other platforms the default values are the same as the default values for version 1.4.2.

In the J2SE platform version 1.4.2 by default the following selections were made

  • initial heap size of 4 Mbyte
  • maximum heap size of 64 Mbyte

Solution 3:

Java 8 takes more than 1/64th of your physical memory for your Xmssize (Minimum HeapSize) and less than 1/4th of your physical memory for your -Xmxsize (Maximum HeapSize).

You can check the default Java heap size by:

In Windows:

java -XX:+PrintFlagsFinal -version | findstr /i "HeapSize PermSize ThreadStackSize"

In Linux:

java -XX:+PrintFlagsFinal -version | grep -iE 'HeapSize|PermSize|ThreadStackSize'

What system configuration settings influence the default value?

The machine's physical memory & Java version.

Solution 4:

This is changed in Java 6 update 18.

Assuming that we have more than 1 GB of physical memory (quite common these days), it's always 1/4th of your physical memory for the server vm.

Solution 5:

Finally!

As of Java 8u191 you now have the options:

-XX:InitialRAMPercentage
-XX:MaxRAMPercentage
-XX:MinRAMPercentage

that can be used to size the heap as a percentage of the usable physical RAM. (which is same as the RAM installed less what the kernel uses).

See Release Notes for Java8 u191 for more information. Note that the options are mentioned under a Docker heading but in fact they apply whether you are in Docker environment or in a traditional environment.

The default value for MaxRAMPercentage is 25%. This is extremely conservative.

My own rule: If your host is more or less dedicated to running the given java application, then you can without problems increase dramatically. If you are on Linux, only running standard daemons and have installed RAM from somewhere around 1 Gb and up then I wouldn't hesitate to use 75% for the JVM's heap. Again, remember that this is 75% of the RAM available, not the RAM installed. What is left is the other user land processes that may be running on the host and the other types of memory that the JVM needs (eg for stack). All together, this will typically fit nicely in the 25% that is left. Obviously, with even more installed RAM the 75% is a safer and safer bet. (I wish the JDK folks had implemented an option where you could specify a ladder)

Setting the MaxRAMPercentage option look like this:

java -XX:MaxRAMPercentage=75.0  ....

Note that these percentage values are of 'double' type and therefore you must specify them with a decimal dot. You get a somewhat odd error if you use "75" instead of "75.0".