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:
import java.util.*; import java.lang.*; public class OOMTest{ public void stackOverFlowMethod(){ stackOverFlowMethod(); } public static void main(String... args){ OOMTest oom = new OOMTest(); oom.stackOverFlowMethod(); } }
The output of the above code:
Exception in thread "main" java.lang.StackOverflowError at OOMTest.stackOverFlowMethod(OOMTest.java:6)
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.
import java.util.*; import java.lang.*; public class OOMTest{ public static void main(String... args){ List<byte[]> buffer = new ArrayList<byte[]>(); buffer.add(new byte[10*1024*1024]); } }
Below is the command to run this program.
java -verbose:gc -Xmn10M -Xms20M -Xmx20M -XX:+PrintGC OOMTest
Here is the output:
[GC 1180K->366K(19456K), 0.0037311 secs] [Full GC 366K->330K(19456K), 0.0098740 secs] [Full GC 330K->292K(19456K), 0.0090244 secs] Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at OOMTest.main(OOMTest.java:7)
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:
import java.util.*; import java.lang.*; public class OOMTest{ public static void main(String... args){ List<String> list = new ArrayList<String>(); while(true){ list.add(UUID.randomUUID().toString().intern()); } } }
Run the program with command:
java -verbose:gc -Xmn5M -Xms10M -Xmx10M -XX:MaxPermSize=1M -XX:+PrintGC OOMTest
Output is :
Exception in thread "main" java.lang.OutOfMemoryError: PermGen space at java.lang.String.intern(Native Method) at OOMTest.main(OOMTest.java:8)
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:
threads space = 4G-(-Xmx value)- (-XX:MaxPermSize value)- program counter register
So if want to get away with this error, need to increase the thread space by changing -Xmx and -XX:MaxPermSize accordingly.
Reference : http://imtiger.net/blog/2009/10/02/java-oom-summary/