In-depth understanding of java virtual machine study notes 1 (java memory area and memory overflow exception)

1. Data area during runtime of java virtual machine


Data area shared by all threads: Heap, Method Area
Thread-isolated data area: VM Stack, Native Method Stack, Program Counter Register
1.1 In the conceptual model, the bytecode interpreter works by changing the value of the program counter of the current thread To select the next bytecode instruction to be executed
1.2 The virtual machine stack serves the virtual machine to execute the java method. When each method is executed, a frame stack is created to store the local variable table, operation stack, dynamic link, and method exit. And other information.
The process from when each method is called to the completion of execution corresponds to the process of a frame stack from pushing to popping in the virtual machine stack.
1.3 The local method stack executes the local method service for the virtual machine.
1.4 Heap is created when the virtual machine starts. The sole purpose of this memory area is to store object instances. The heap can be subdivided into the new generation and the old generation.
1.5 Method area for storing virtual machines. Data such as class information, constants, static variables, and code compiled by the just-in-time compiler loaded by the machine.

2. Object access

There are two mainstream object access methods: using handles and direct pointers

3. Actual combat oom is abnormal

3.1java heap overflow

/**
 * @Title: HeapOOM
 * @Description: -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:/home/
 * @date 2020/4/15 17:57
 */
public class HeapOOM {
    static class OOMObject{}

    public static void main(String[] args) {
        List<OOMObject> list = new ArrayList<>();
        while (true){
            list.add(new OOMObject());
        }
    }
}

operation result:

3.2 Virtual machine stack and native method stack overflow

/**
 * @Title: JavaVMStackSOF
 * @Description: -verbose:gc -Xms20M -Xss128K -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:/home/
 * @date 2020/4/16 9:08
 */
public class JavaVMStackSOF {
    private int stackLength = 1;

    private void stackLeak(){
        stackLength++;
        stackLeak();
    }

    public static void main(String[] args) {
        JavaVMStackSOF oom = new JavaVMStackSOF();
        try {
            oom.stackLeak();
        } catch (Throwable e) {
            System.out.println("stack length:" + oom.stackLength);
            throw e;
        }
    }
}

The result of the operation is only StackOverflowError

3.3 Creating a thread causes memory overflow

/**
 * @Title: javaVMStackOOM
 * @Description: -verbose:gc -Xms20M -Xss2M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:/home/
 * @date 2020/4/16 9:33
 */
public class JavaVMStackOOM {
    private void dontStop(){
        while (true){}
    }

    public void stackLeakByThread(){
        while (true){
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    dontStop();
                }
            });
            thread.start();
        }
    }

    public static void main(String[] args) {
        JavaVMStackOOM oom = new JavaVMStackOOM();
        oom.stackLeakByThread();
    }
}

It is easy to crash after running, and there is no result when running.

3.4 Runtime constant pool overflow

When testing the overflow code in the method area according to the document 2.4.3, it was found that a long time has passed and no memory overflow occurred. After reading the document, I learned that the permanent code was removed after jdk1.7.

//-XX:PermSize=10M -XX:MaxPermSize=10M
public class RuntimeConstantPoolOOM {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        int i = 0;
        while (true){
            list.add(String.valueOf(i++).intern());
        }
    }
}

Before here, in addition to just-in-time compiled code stored in Native memory, other data, including class information, constants, static variables, constant pools, etc., are stored in the permanent generation. However, there is a problem in this way, that is, memory leaks are prone to occur.

Therefore, in jdk8, the permanent generation is completely removed and replaced by metaSpace. The concept of method area is kept in the metaspace, and the constant pool is in the heap.

The method area is just a concept defined in the JVM specification . It is used to store data such as class information, constant pools, static variables, and JIT-compiled code. Where it is placed, different implementations can be placed in different places. The permanent generation is a unique concept of the Hotspot virtual machine, which is an implementation of the method area, which is not available in other JVMs.

Before jdk1.7: The method area is located in the permanent generation (PermGen). The permanent generation and the heap are isolated from each other. The size of the permanent generation can be set to a fixed value when the JVM is started, and it is immutable;
jdk.7: Part of the data stored in the permanent generation is just Has been transferred to Java Heap or Native memory. However, the permanent generation still exists in JDK 1.7 and has not been completely removed. For example, symbol references (Symbols) are transferred to native memory; interned strings are transferred to the Java heap; class statics variables are transferred. To the Java heap;
jdk1.8: The concept of method area is still retained, but the implementation is different. Cancel the permanent generation, and the method is stored in the metaspace. The metaspace is still not connected to the heap, but it shares physical memory with the heap, which can logically be considered to be in the heap.

1) Removed the permanent generation (PermGen) and replaced it with Metaspace;
2) The class metadata in the permanent generation was transferred to native memory (local memory, not virtual machine);
3) Interned Strings and the permanent generation The class static variables are transferred to the Java heap;
4) Permanent generation parameter (PermSize MaxPermSize) -> Metaspace parameter (MetaspaceSize MaxMetaspaceSize).

3.5 Method area overflow

public class JavaMethodAreaOOM {
    static class OOMObject{}

    public static void main(String[] args) {
        while (true){
            Enhancer enHancer = new Enhancer();
            enHancer.setSuperclass(OOMObject.class);
            enHancer.setUseCache(false);
            enHancer.setCallback(new MethodInterceptor() {
                @Override
                public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                    return methodProxy.invoke(o, args);
                }
            });
        }
    }
}

jdk1.7 virtual machine parameters: -XX:PermSize=10M -XX:MaxPermSize=10M 

operation result:

jdk1.8 virtual machine parameters: -XX:MetaspaceSize=10M -XX:MaxMetaspaceSize=10M

operation result:

The heap overflow of the jdk1.7 operation result indicates that the class information is indeed put in the heap.

The Metaspace overflow of the jdk1.8 running result indicates that the class information is indeed placed in the Metaspace.

3.6 Native direct memory overflow

//-Xmx20M -XX:MaxDirectMemorySize=10M
public class DirectMemoryOOM {
    private static final int _1M = 1024 * 1024;

    public static void main(String[] args) throws Exception {
        Field unsafeField = Unsafe.class.getDeclaredFields()[0];
        unsafeField.setAccessible(true);
        Unsafe unsafe = (Unsafe) unsafeField.get(null);
        while (true){
            unsafe.allocateMemory(_1M);
        }
    }
}

operation result:

Guess you like

Origin blog.csdn.net/noob9527/article/details/105559659