Worse, the one time this swapping is guaranteed to occur is during a full GC, when the JVM
must access the entire heap. If the system is swapping during a full GC, pauses will be an or-
der of magnitude longer than they would otherwise be. Similarly, if a concurrent collector is
used, when the background thread sweeps through the heap, it will likely fall behind due to
the long waits for data to be copied from disk to main memory—resulting in an expensive
concurrent mode failure.
Hence, the first rule in sizing a heap is never to specify a heap that is larger than the amount
of physical memory on the machine—and if there are multiple JVMs running, that applies to
the sum of all their heaps. You also need to leave some room for the JVM itself, as well as
some memory for other applications: typically, at least 1 GB of space for common OS pro-
The size of the heap is controlled by two values: an initial value (specified with -Xms N ) and a
maximum value ( -Xmx N ). The defaults for these vary depending on the operating system, the
amount of system RAM, and the JVM in use. The defaults can be affected by other flags on
the command line as well; heap sizing is one of the JVM's core ergonomic tunings.
The goal of the JVM is to find a “reasonable” default initial value for the heap based on the
system resources available to it, and to grow the heap up to a “reasonable” maximum if (and
only if) the application needs more memory (based on how much time it spends performing
GC). Absent some of the advanced tuning flags and details discussed later in this and the
next chapters, the default values for the initial and maximum sizes are given in Table 5-4 .
(The JVM will round these values down slightly for alignment purposes; the GC logs that
print the sizes will show that the values are not exactly equal to the numbers in this table.)