Friday, November 11, 2016

Troubleshooting Java[tm]: Error Occurred During Initialization of VM: Could not reserve enough space for object heap

Java SE JDK and JRE - Version 6 to 8
Information in this document applies to any platform.

Purpose

This troubleshooting guide should help you to diagnose an issue that occurs right after you try to start a Java program; even when "java -version" quits.  Dependent on the Java version, the error message that you get is either this three line error message
Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.

or a two line error message:
Error occurred during initialization of VM
Could not reserve enough space for object heap
or a four line error message:
Error occurred during initialization of VM
Could not reserve enough space for object heap
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.

Troubleshooting Steps

1. Check whether -Xmx has been set explicitly or not (32 bit or 64 bit JVM)

If you don't specify -Xmx explicitly, the default selection for the maximum heap size could be implicitly set by the Ergonomics feature of the JVM that was added in JDK 5.
See also
http://www.oracle.com/technetwork/java/ergo5-140223.html
http://download.oracle.com/javase/6/docs/technotes/guides/vm/gc-ergonomics.html

The Ergonomics algorithm does not take the memory into account that is available on the system during startup. If a system has 8 GB of memory and ergonomics selects a default of 2 GB for the max Java heap size, the JVM could fail during initialization if the 2 GB cannot be reserved.

Example:
$ java -version
Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.


Solution:
Specify -Xmx explicitly. Make sure that there is enough memory available on the system for the value that you specify for the max Java heap.
java -Xmx128m -version

If you use JDK 6 you can also set the ErgoHeapSizeLimit JVM option - the maximum ergonomically set heap size (in bytes):
java -XX:ErgoHeapSizeLimit=128m -version


2. Check whether -d64 has been set (64 bit JVM on Solaris only)

If you want to use the 64-bit JVM on Solaris, both the 32-bit and the 64-bit JVM must be installed to the same folder. In order to select the 64 bit JVM, the -d64 option has to be specified. On Solaris you can use "/usr/bin/pargs <pid>" to check whether the -d64 option has been set for your process.
Example:
If you run the JVM on Solaris with:
java -Xmx4000m -version
and if you can reproduce the error, you are probably running a 32 bit JVM instead of the 64 bit JVM.
Solution:
Set the -d64 option explicitly in order to use the 64 bit JVM on Solaris.

Example:
If you run the JVM on Solaris with:
java -d64 -Xmx4000m -version
you won't be able to reproduce the error anymore.

3. Check whether the value for -Xmx  has been set too large (32 bit JVM only)

32-bit architectures limit the amount of memory any single process can allocate to 4 GB (theoretical address space is 2^32 bytes). However, there is memory overhead that the JVM and the Operating System use for a Java process. A Java process space consists of the Java heap, the Java permanent generation, the native heap, the threads, mapped files, loaded shared libraries and so on. If you run a 32-bit JVM, the maximum value for the java heap (-Xmx) of a Java process is much smaller than 4 GB actually.  The actual value will depend on the Operating System involved and what is actually running on the system.  A rough rule of thumb provides a maximum 32-bit process size of 3G for Solaris systems and about 2.5G for Linux systems.

There is a limitation of the Windows 32-bit Operating System involving maximum process memory allocation. Windows 32-bit processes can only use a max of 2 GB memory address space. Although Windows does allow a process size > 2 GB through its "Physical Address Extension (PAE)", the HotSpot JVM currently does not use this feature.

See also the MSDN article on Memory Limits for Windows Releases.

Examples:
If you run a 32-bit JVM on Solaris with:
java -Xmx4000m -version
or if you run it on Linux with:
java -Xmx3000m -version
or if you run it on Windows with:
java -Xmx2000m -version
you will be able to reproduce the error.
Notes:
  • If you want to perform any tests, test with a small Java program or with the -version option in order to initialize the JVM. Don't test with -fullversion since it won't initialize the JVM.
  • You can also get the two-line error message rather than the three-line error message if the value is very large, but smaller than the maximum representable size of the Java heap (e.g. "java -Xmx 4050m -version" on Solaris)

Solution:
Decrease the Java Heap Space value (-Xmx) to a reasonable value that takes all the other memory usage for the process into account or move to a 64-bit architecture (64-bit machine, 64-bit Operating System, and a 64-bit JRE).

Examples:
If you run a 32-bit JVM on Solaris with:
java -Xmx3500m -version
or if you run it on Linux with:
java -Xmx2600m -version
or if you run it on Windows with:
java -Xmx1400m -version
you won't be able to reproduce the error anymore.

Please note that in certain circumstances, even moving to a 64-bit environment will not help.  In environments where the resources available are managed, such as in a Solaris zone or an OS running under a hypervisor, the environment may not have more than 4G with which to work.  In these cases, you will need to ensure that your 64-bit environment is provided with the resources you need to successfully run your JVM. See also section 6.

4. Check whether the system is low on virtual memory (32 bit or 64 bit JVM)

Example:
If swap is exhausted and if you run a 64 bit JVM on Solaris with:
java -Xmx4096m -version
you will be able to reproduce the error.

On Solaris you can use the swap command in order to determine whether you have enough virtual memory available:
$ /usr/sbin/swap -s
total: 2519040k bytes allocated + 15706520k reserved = 18225560k used, 167896k available

In the example above, there are only 163.96 Mb virtual memory available, which might not be enough for starting another big Java app because the Java heap needs a reliable backing store (swap).
Notes:
  • If the system is low on virtual memory, you get the two-line error message rather than the three-line error message.
  • The error message does appear on 32-bit or 64-bit JVMs, when swap space is exhausted.


Solution:
Decrease the -Xmx value, don't run too many heavy processes on the system, and/or configure more swap.
Note:

It is ok if non-active processes are using swap space.  However, if actively used processes are constantly having their pages moved back and forth from RAM to disk based swap areas, performance will suffer dramatically. So if you configure more swap, take into account that it may also be necessary to buy more physical memory. See also Note:1262554.1.

Example:

If swap is not exhausted and if you run a 64 bit JVM on Solaris with:
java -Xmx4096m -version
you won't be able to reproduce the error anymore.

5. Check Limitations on the System Resources in the current shell (Linux and Solaris only)

On both Linux and Solaris the stack size is controlled by setting limitations on the system resources available to the current shell and its descendants.

On Windows platforms, the stack size information is contained in the executable file.

5.1 In which shell does the application run?

On Solaris, use ptree or pargs in order to check what shell you are actually using. The special shell variable $$ provides the shell's process id. Example:
$ /usr/bin/ptree | grep $$ | grep -v grep
  15520 /bin/csh

or
$ pargs $$
1131:     ksh
argv[0]:  ksh

In the fist example, you use the csh, in the second example, you use the ksh.

On Linux, use pstree. Example:
/usr/bin/pstree $$
bash---pstree

In the example above, you use the bash.

5.2 Check if the Virtual Memory Limit is set too small

Example:
$ ulimit -v
60000
ShellCheck
sh/ksh/bash ulimit -v
csh limit memorysize
tsch limit vmemoryuse


Solution:
Decrease the Java Heap (-Xmx) or remove the limitations on the system resources available to the current shell.
ShellSet
sh/ksh/bash ulimit -v unlimited
csh limit memorysize unlimited
tsch limit vmemoryuse unlimited


See also: man limit

5.3 Check if the stack size is set to unlimited (Solaris SPARC only)

Example:
$ ulimit -s
unlimited
ShellCheck
sh/ksh/bash ulimit -s
csh limit stacksize
tcsh limit stacksize

On Solaris SPARC setting the stacksize (not to be confused with the per thread stack) to "unlimited" assigns a 2 GByte limit to the stacksize of the process.


That leaves just 2 Gb for the Java heap, the Java perm generation, the native heap, the threads, mapped files, loaded shared libraries and so on. Those 2 Gb frequently won't be enough.


Solution:
for 32-bit JVM: ensure that stacksize is set to a reasonable value (e.g. 8192 kbytes, NOT "unlimited"). Example:
ShellSet
sh/ksh/bash ulimit -s 8192
csh limit stacksize 8192
tcsh limit stacksize 8192

6. Check Solaris Resources

6.1. Process control which limits the process size

Use prctl [pid] to check.


6.2. Check zone configuration which limits physical/swap

Use zonecfg to check.

7. Check for Linux kernel specific bugs

See also note:1625806.1 Java SE 7 Produces error "Could not reserve enough space for object heap" in RedHat 6 Servers with Linux Kernels 2.6.32-358.11.1.el6.i686 or Later

No comments:

Post a Comment