Reprinted from HTTPS://GITHUB.COM/PZXWHC/MINEKNOWCONTAINER/ISSUES/25
Including:
1. Stack Overflow (stackoverflowerror)
2. Heap overflow (Outofmemoryerror:java heap space)
3. Permanent generation overflow (outofmemoryerror:permgen space)
4. Outofmemoryerror:unable to create native thread
The Java Virtual Machine specification specifies that the JVM's memory is divided into chunks, such as heaps, stacks, program counters, method areas, and so on, while the implementation of the hotspot JVM divides the heap memory into two parts: The new generation, the old age. In addition to the heap memory, there are permanent generations, where the permanent generation implements the method area specified in the specification, and the corresponding Oom error occurs in different parts of the memory model, and then we will discuss it separately.
Stack Overflow (stackoverflowerror)
Stack overflow throws a stackoverflowerror error, which occurs because the stack depth exceeds the maximum allowable depth of the virtual machine when the method is running. This situation, in general, is caused by a program error, such as writing a dead recursion, it is possible to cause this situation. Let's use a piece of code to simulate a memory overflow 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 will throw the following exception:
Exception in thread "main" java.lang.StackOverflowError at OOMTest.stackOverFlowMethod(OOMTest.java:6)
For stack memory overflow, according to the Java Virtual Machine Specification Chinese version: If the thread requests a stack capacity that exceeds the maximum allowable capacity of the stack, the Java virtual machine throws a StackOverflow exception, and if the Java Virtual machine stack can be dynamically extended, and the extended action has been tried, However, the Java virtual machine throws a OutOfMemory exception if it cannot request enough memory to complete the extension, or if there is not enough memory to create the corresponding virtual machine stack when the new thread is created.
Heap Overflow (Outofmemoryerror:java heap space)
Heap memory overflow, virtual opportunity throws Java.lang.OutOfMemoryError:java heap space, in this case, we need to based on the memory overflow when the dump file generated by the specific analysis (need to increase-xx:+ HEAPDUMPONOUTOFMEMORYERRORJVM startup parameters). This can be a memory leak, or a memory overflow may be the case.
- If memory leaks, we want to find out how the compromised object was referenced by GC root, and then use the reference chain to specifically analyze the cause of the leak.
- If there is a memory overflow problem, this is often the program native needs more memory than we give the virtual machine configuration of memory, in this case, we can use the-XMX to solve this problem. Let's demonstrate the overflow of this situation by 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 outputs 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)
From the running results can be seen, the JVM carried out a minor GC and two times of the major GC, from the output of the major GC can be seen, the GC after the old area is 134K, and the byte array is 10M, plus more than the old generation space, so throw an exception , if the-xms21m,-xmx21m is adjusted, then the GC operation will not be triggered and no exception will occur.
Through the above experiments in fact also verified from the side of the conclusion: when the object is larger than the remaining memory of the new generation, will be placed directly into the old age, when the old age remaining memory can not be put down, triggered garbage collection, after collection or can not put down will throw memory overflow exception.
Persistent belt overflow (outofmemoryerror:permgen space)
We know that the hotspot JVM implements the method area in the Java Virtual Machine specification through the persistence band, while the constant pool at run time is saved in the method area, so the persistence overflow is likely to run a constant pool overflow. It is also possible that the class object saved in the method area has not been reclaimed in time or that the class information occupies more memory than we configured.
Throws Java.lang.OutOfMemoryError:PermGen space when the persistent band overflows. There are several scenarios that may appear:
- With some application server hot deployment, we will encounter a hot deployment a few times after the memory overflow, this situation is because after each hot deployment, the original class was not unloaded.
- This can also occur if the application itself is larger and the class libraries involved are more, but the memory that we allocate to the persistence band (set by-xx:permsize and-xx:maxpermsize) is relatively small.
- Some third-party frameworks, such as spring,hibernate, use bytecode generation techniques (such as cglib) to implement some of the enhanced functionality that might require a larger method area to store dynamically generated class files.
We know that the string constants in Java are placed in a constant pool, and when String.intern () is run, it checks to see if the constant pool has an object that is equal to this string, and if there is a reference to the object in the constant pool that does not exist, add the string to the constant pool first. It then returns a reference to the string. Then we can simulate the overflow of the run-time area by the String.intern method. 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 the run is as follows:
Exception in thread "main" java.lang.OutOfMemoryError: PermGen space at java.lang.String.intern(Native Method) at OOMTest.main(OOMTest.java:8)
Through the above code, we successfully simulated the operation of the constant pool overflow situation, from the output of PermGen space can be seen that there is indeed a persistent band overflow, which also verifies that we said before the hotspot JVM through the persistence of the implementation of the method area.
Outofmemoryerror:unable to create native thread
Finally we are looking at java.lang.OutOfMemoryError:unable to create Natvie thread this error. When this happens, it is generally caused by the following two conditions:
1. The number of threads created by the program exceeds the operating system limit. For Linux systems, we can view this restriction through ulimit-u.
2. The memory allocated to the virtual machine is too large, causing the thread to be created with too little native memory.
We all know that the operating system is limited to the memory of each process, we start the JVM, the equivalent of starting a process, if we have a process that consumes 4G of memory, then the remaining memory calculated by the following formula is the memory that can be used to establish the line stacks. Line stacks total available memory =4g-(value of-XMX)-(value of-xx:maxpermsize)-memory occupied by program counters
As we can see from the above formula, the larger the value of-XMX and MaxPermSize, the smaller the amount of space left to the thread stack, and the smaller the number of threads that can be created if the stack capacity of the-XSS parameter configuration is constant. So if the unable to create native thread is caused by this situation, either we increase the total memory occupied by the process, or reduce the-xmx or-XSS to achieve the purpose of creating more threads.
Summarize:
- Stack memory overflow: The stack depth required by the program is too large to cause.
- Heap memory overflow: Distinguish between memory leaks or insufficient memory capacity. Leaks See how the object is referenced by GC Root. The-XMS,-XMX parameter is adjusted by the large size.
- Persistent Memory overflow: Class object is not freed, class object occupies too much information, there are too many class objects.
- Unable to create local thread: The total capacity is unchanged, heap memory, non-heap memory settings are too large, resulting in insufficient memory to the thread.
Java JVM: Memory overflow (stack overflow, heap overflow, persistent overflow, and nable to create native thread)