Memory related exception analysis in Java

Java Virtual Machine Specification divides the memory of JVM into several areas : Heap, Stack, The Program Counter register and Method area etc. In HotSpot JVM, heap is composed of Young, Tenured and Perm. There are different OutOfMemory error can happen in different memory area. Next is an overview of some of these OOM errors.

StackOverflowError

The JVM will allow only a specified number of stacks created nested. An JVM option -Xss can be set to determine the maximum stack size. If the number of stacks created is more than the maximum allowed, a java.lang.StackOverflowError will be thrown. Usually it indicates there is a program error if this exception is thrown. For example, a dead recursion. Below is a code snippet to demonstrate this:

OutOfMemoryError:java heap space

If too much heap space is allocated, for example, a very large array creation, java.lang.OutOfMemoryError:java heap space may be thrown. To analyze this kind of error, a dump is often needed. This can be achieved by setting the JVM option -XX:+HeapDumpOnOutOfMemoryError. Below is a code snippet to demonstrate this.

From the output, JVM does one minor GC nad two major GCs. According to major GC, 134K is used in tenured area after the GC, And the byte array takes 10M. Summing them up is greater than the space of the tenured area, so an exception is thrown.

OutOfMemoryError: PermGen space

HotSpot JVM has the method area in the Perm space, the runtime constant pool is stored in the method area. If there is OutOfMemortError in PermGen space, it may be caused by the constant pool overflow or objects in method area are not gced timely or the size of the objects exceeds the settings.

Below scenarios may cause the OutOfMemoryError: PermGen space:

1. Multiple hot deployments where the old objects are not removed

2. The application itself takes much space, for example, it has two many dependencies

3. Some third party frameworks(Spring and Hibernate) uses some byte code generation tools to enhance their functions.

String literals are stored in the constant pool, when String.intern() is called, it will check whether the string is already in the pool, if yes, the reference to the literal will be returned directly; if no, the string literal will be stored in the constant pool and the reference will be returned. Below is the code snippet which uses the String.intern() to demonstrate the OutOfMemoryError:PermGen space:

OutOfMemoryError:unable to create native thread

If a java.lang.OutOfMemoryError:unable to create natvie thread is seen, most probably it is caused by below :

1. The number of threads exceeds the maximum allowed by the system. For example, ulimit -u can be run to check how many threads are allowed in Linux

2. The memory allocated to the JVM is too large and at the same time the size allocated to the threads are too small. Every process can only be used a specified amount of memory. When the JVM is launched, a process is created and it can only use a specified amount of memory, for example, 4G. Below formula can be used to calculate the space the threads can take: