Java common memory overflow exception analysis and resolution

  • 2020-05-12 02:32:53
  • OfStack

Java the rules and regulations of the virtual machine JVM memory is divided into several blocks, such as heap, stack, the program counter, method of area, etc., and Hotspot jvm implementation, the heap memory is divided into three parts, the new generation, old age, lasting belt, including persistent with implements the method specified in the specifications section, and the different part of the memory model will appear the corresponding OutOfMemoryError error, then we will separate to discuss under 1. java.lang.OutOfMemoryError this is an error that I believe most developers have encountered, and it is mostly due to the following reasons:

JVM's memory is too small, the program is not rigorous, and produces too much garbage.

There are several common reasons for OutOfMemoryError anomalies:

The amount of data loaded in memory is too large, such as 1 time from the database to extract too much data; There is a reference to the object in the collection class, which is not emptied after use, so JVM cannot be recycled. There is a dead loop in the code or the loop produces too many repeating object entities; BUG in the third party software used; Startup parameter memory value setting is too small;

Common errors for this error are:

tomcat:java.lang.OutOfMemoryError: PermGen space tomcat:java.lang.OutOfMemoryError: Java heap space weblogic:Root cause of ServletException java.lang.OutOfMemoryError resin:java.lang.OutOfMemoryError java:java.lang.OutOfMemoryError

Stack overflow (StackOverflowError)

Stack overflow throws the java.lang.StackOverflowError error, which occurs because the stack depth exceeds the maximum allowable depth of the virtual machine while the method is running. In this case, 1 is the result of a programming error, such as writing a dead recursion. Let's use a piece of code to simulate a memory leak in this case.


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(); 
 } 
} 

Running the above code throws the following exception:


Exception in thread "main" java.lang.StackOverflowError 
    at OOMTest.stackOverFlowMethod(OOMTest.java:6) 

Heap overflow (OutOfMemoryError:java heap space)

Heap memory, virtual opportunity thrown java. lang. OutOfMemoryError: Java heap space, appear this kind of situation, we need according to the memory of dump files to specific analysis (need to increase - XX: + HeapDumpOnOutOfMemoryErrorjvm launch parameters). This can be a memory leak or a memory leak.

If memory leaks, we need to find out how the leaked object is referenced by GC ROOT, and then analyze the cause of the leak through the reference chain.

If there is a memory overflow problem, it is usually because the program itself needs more memory than we configured for the virtual machine. In this case, we can adjust the size of -Xmx to solve this problem.

Let's demonstrate this overflow in 1 with the following code:


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]); 
    } 
  
} 

We run the above code with the following command:


java -verbose:gc -Xmn10M -Xms20M -Xmx20M -XX:+PrintGC OOMTest

The program enters the following information:


[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) 

As can be seen from the running results, JVM conducted Minor gc once and Major gc twice. As can be seen from the output of Major gc, after gc, the utilization rate of old area is 134K, while the byte array is 10M, which adds up to more than the space of old generation, so an exception is thrown. If you adjust -Xms21M, -Xmx21M, then the gc operation will not be triggered and there will be no exception.

In fact, the above experiment also verified a conclusion from the side: when the object is larger than the remaining memory of the new generation, it will be directly put into the old age; when the remaining memory of the old age still cannot be put down, garbage collection will be triggered, and memory overflow exception will be thrown if it cannot be put down after collection

Persistent band overflow (OutOfMemoryError: PermGen space)

We know Hotspot jvm Java virtual machine specification by persistent belt and methods in the area, and the runtime constant pool is kept in the method of area, so persistent with overflow is probably the runtime constant pool overflow, it is possible that the method of class object had not been kept in a district in time off or class information memory than we configuration. java.lang.OutOfMemoryError: PermGen space.
I may have this problem in the following scenarios at work.

When using hot deployment of some application servers, we will encounter hot deployment several times and find out that the memory is running out, which is because the original class is not uninstalled after each hot deployment.

This can happen when the application itself is large and involves more libraries, but the memory we allocate to persistent bands (set by -XX :PermSize and -XX :MaxPermSize) is small.

Some third party frameworks, such as spring and hibernate, implement some of the enhancements through bytecode generation techniques (such as CGLib), which may require a larger method area to store dynamically generated Class files.

We know Java string constants are put in the constant pool, String. intern () this method operation, will check whether the deposit and the strings are equal in the constant pool, if there is a direct return object reference, in the constant pool does not exist, add the string constant pool first, and then returns a string reference. String.intern method can be used to simulate overflow in the constant region of 1 runtime. The following code is used to simulate this situation:


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()); 
        } 
    } 
  
} 

We run the above code with the following command:


java -verbose:gc -Xmn5M -Xms10M -Xmx10M -XX:MaxPermSize=1M -XX:+PrintGC OOMTest

The input after running is shown in the following figure:


Exception in thread "main" java.lang.OutOfMemoryError: PermGen space 
    at java.lang.String.intern(Native Method) 
    at OOMTest.main(OOMTest.java:8) 

With the code above, we successfully simulated the overflow of the constant pool at run time. From the PermGen space in the output, we can see that the overflow of the persistent band did occur, which also verified our previous statement that Hotspot jvm implements the method section through the persistence band.

OutOfMemoryError:unable to create native thread

Finally we came to see java. lang. OutOfMemoryError: unable to create natvie thread such mistakes. When this happens, 1 is usually caused by the following two conditions:

The number of threads created by the program exceeds operating system limits. For the Linux system, we can view this restriction through ulimit-u.

Too much memory is allocated to the virtual machine, resulting in too little native memory required to create threads. We all know that the operating system has a limit on the memory of each process. If we start Jvm, it is equivalent to starting one process. If one process occupies 4G's memory, then the remaining memory calculated by the following formula is the memory that can be used when setting up the thread stack. The total available memory of thread stack =4G- (-Xmx value) - (-XX :MaxPermSize value) - the memory occupied by program counter from the above formula, we can see that the larger the values of -Xmx and MaxPermSize are, the less space is available for thread stack, and the smaller the number of threads can be created under the condition that the stack capacity configured with -Xss parameter remains the same. So if unable to create native thread is the result of this situation, then either we increase the total memory used by the process, or we decrease -Xmx or -Xss to create more threads.


Related articles: