JVM memory region and memory overflow exception

All Rights Reserved © jackiegu.cn

1. JVM runtime memory data area division

  • Program counter
  • Java virtual machine stack
  • Native Method Stack
  • Java heap
  • Method area
  • Runtime Constant Pool

2. Program counter

The program counter is a small memory space, which can be understood as the line number indicator of the bytecode file executed by the current thread. The basic functions such as branch, loop, jump, exception handling and thread recovery need to be completed by this counter;

The program counter is a private data area of threads. Each thread needs an independent program counter. The counters between threads do not affect each other and are stored independently, so that the thread can be restored to the correct execution position after thread switching;

When the program counter is a Native method executed by the thread, its counter value is empty;

The program counter is the only area that does not specify any OutOfMemoryError in the Java virtual machine specification;

Actual combat cases:

package cn.jackiegu.jvm.study.memory;

public class ProgramCounterRegisterTest {

    public static void main(String[] args) {
        Thread thread0 = new Thread(new R0());
        Thread thread1 = new Thread(new R1());
        thread0.start();
        thread1.start();
    }
}

class R0 implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            // Break point
            System.out.println("thread0: " + i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class R1 implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            // Break point
            System.out.println("thread1: " + i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

Mark the break point of thread pause in the run methods of R0 and R1 respectively, and then run the main function in the Debug mode;

Thread-0 and Thread-1 here are the two threads created in the main function;

Select one of the thread breakpoints, and then the content displayed below (the content in the red box) can be understood as the Java class and code line number being executed by the current thread, which is also the content recorded by the program counter. Its content will also change when the thread is switched; For example: run:37, R1(cn.jackiegu.jvm.study.memory) indicates that the current thread is executing to CN jackiegu. jvm. study. In the run method of R1 class under the memory package, the code line number is 37;


3. Java virtual machine stack

Java virtual machine stack is also a thread private data area, and its life cycle is the same as that of thread;

Java virtual machine stack describes the thread memory model of Java method execution: when each method is executed, Java virtual machine will synchronously create a stack frame to store local variables, operand stack, dynamic connection, method exit and other information; The process of each method being called until it is executed corresponds to the process of a stack frame from entering the stack to leaving the stack in the virtual machine stack;

In the Java virtual machine stack, if the stack depth requested by the thread is greater than the allowable depth of the virtual machine, a StackOverflowError exception will be thrown; If the stack capacity of Java virtual machine can be dynamically expanded (the stack capacity of HotSpot virtual machine cannot be dynamically expanded), when the stack cannot be applied for enough memory, OutOfMemory exception will be thrown;

The stack size of each thread in the Java virtual machine stack can be set through - Xss;

Actual combat cases:

Test 1:

package cn.jackiegu.jvm.study.memory;

public class JavaVirtualMachineStackTest {

    private Integer number = 1;

    public void overflow() {
        this.number++;
        overflow();
    }

    public static void main(String[] args) {
        JavaVirtualMachineStackTest javaVirtualMachineStackTest = new JavaVirtualMachineStackTest();
        try {
            // StackOverflowError exception test
            javaVirtualMachineStackTest.overflow();
        } catch (Error e) {
            System.out.println(javaVirtualMachineStackTest.number);
            System.out.println(e);
        }
    }
}
// Operation results
11667
java.lang.StackOverflowError

Test 2:

Overload the overflow method and observe the execution result

package cn.jackiegu.jvm.study.memory;

public class JavaVirtualMachineStackTest {

    private Integer number = 1;

    public void overflow(String message) {
        this.number++;
        char[] chars = new char[message.length()];
        for (int i = 0; i < chars.length; i++) {
            chars[i] = message.charAt(i);
        }
        String newMessage = new String(chars);
        overflow(newMessage);
    }

    public static void main(String[] args) {
        JavaVirtualMachineStackTest javaVirtualMachineStackTest = new JavaVirtualMachineStackTest();
        try {
            // StackOverflowError exception test
            javaVirtualMachineStackTest.overflow("java vm stack");
        } catch (Error e) {
            System.out.println(javaVirtualMachineStackTest.number);
            System.out.println(e);
        }
    }
}
// Operation results
4696
java.lang.StackOverflowError

Test 3:

Set the thread stack size to 128k and observe the execution results

package cn.jackiegu.jvm.study.memory;

public class JavaVirtualMachineStackTest {

    private Integer number = 1;
    
    public void overflow(String message) {
        this.number++;
        char[] chars = new char[message.length()];
        for (int i = 0; i < chars.length; i++) {
            chars[i] = message.charAt(i);
        }
        String newMessage = new String(chars);
        overflow(newMessage);
    }
    
    public static void main(String[] args) {
        JavaVirtualMachineStackTest javaVirtualMachineStackTest = new JavaVirtualMachineStackTest();
        try {
            // StackOverflowError exception test
            javaVirtualMachineStackTest.overflow("java vm stack");
        } catch (Error e) {
            System.out.println(javaVirtualMachineStackTest.number);
            System.out.println(e);
        }
    }
}
// Operation results
723
java.lang.StackOverflowError

Summary: the more variables defined inside the method, the shallower the stack depth requested by the thread; At the same time, the smaller the stack size of the thread is set, the shallower the stack depth requested by the thread is;


4. Local method stack

The role of the local method stack is very similar to that of the Java virtual machine stack. The difference is that the Java virtual machine stack performs Java method services for the virtual machine, while the local method stack serves the local methods used by the virtual machine;

In HotSpot virtual machine, Java virtual machine stack and local method stack are combined into one;

Like the Java virtual machine stack, the local method stack throws StackOverflowError and OutOfMemoryError exceptions respectively when the stack depth overflows or the stack expansion fails;


5. Java heap

Java heap is the largest piece of memory managed by the virtual machine. It is shared by all threads and created when the virtual machine starts;

All object instances and arrays in Java should be allocated on the heap;

Java heap is the memory area managed by garbage collector;

Java heap is implemented according to extensibility for the current mainstream Java virtual machine. The initial memory size and maximum available memory size can be set respectively through the parameters - Xms and - Xmx. If there is no memory in the Java heap to complete the instance allocation and the heap cannot be expanded, the Java virtual machine will throw OutOfMemoryError exception;

Actual combat cases:

package cn.jackiegu.jvm.study.memory;

import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class JavaHeapTest {

    private final Integer randomNumber;

    private final String randomString;

    public JavaHeapTest(Integer randomNumber) {
        this.randomNumber = randomNumber;
        this.randomString = String.valueOf(randomNumber);
    }

    public static void main(String[] args) {
        Random random = new SecureRandom();
        List<JavaHeapTest> list = new ArrayList<>();
        try {
            while (true) {
                list.add(new JavaHeapTest(random.nextInt(99999)));
            }
        } catch (Error e) {
            System.out.println(list.size());
            System.out.println(e);
        }
    }
}
// Operation results
31151587
java.lang.OutOfMemoryError: Java heap space

6. Method area

Like the Java heap, the method area is a memory area shared by all threads, which is used to store type information, constants, static variables, code cache compiled by the real-time compiler and other data loaded by the virtual machine;

The method area has an alias called "non heap" to distinguish it from Java heap;

Permanent generation and meta space is the way that different versions of HotSpot virtual machine implement the method area:

  • Before Java 8, the permanent generation implementation was adopted, and Java. Net was thrown in case of memory overflow Lang. outofmemoryerror: permgen space exception. You can limit the permanent generation size through two configuration parameters - XX:PermSize and - XX:MaxPermSize;
  • Java 8 and later are implemented in meta space, and Java. Net will be thrown in case of memory overflow Lang. outofmemoryerror: Metaspace exception. You can limit the size of the Metaspace through two configuration parameters - XX:MetaspaceSize and - XX:MaxMetaspaceSize;

When the method area cannot meet the new memory allocation requirements, an OutOfMemoryError exception will be thrown;

Actual combat cases:

Set the size of the initial meta space and the maximum meta space to 32m, and observe the execution results

package cn.jackiegu.jvm.study.memory;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;

public class MethodAreaTest {

    public static void main(String[] args) {
        int i = 0;
        try {
            while (true) {
                i++;
                Enhancer enhancer = new Enhancer();
                enhancer.setSuperclass(OOM.class);
                enhancer.setUseCache(false);
                enhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> methodProxy.invokeSuper(o, args));
                enhancer.create();
            }
        } catch (Error e) {
            System.out.println(i);
            System.out.println(e);
        }
    }
}

class OOM {

}
// Operation results
3176
java.lang.OutOfMemoryError: Metaspace

7. Runtime constant pool

The runtime constant pool is a part of the method area. An item of information in the Class file is the constant pool table, which is used to store various literal quantities and symbol references generated by the compiler. This part will be stored in the runtime constant pool of the method area after the Class is loaded, and the direct references translated by symbol references will also be stored in the runtime constant pool;

The running constant pool is not a constant pool preset in the Class file. The contents of the constant pool can be entered only. During running, you can also put new constants into the pool, such as string Intern() function;

When the runtime constant pool cannot apply for memory, it will throw OutOfMemoryError exception;


8. Direct memory

Direct memory is not a part of the data area of the virtual machine runtime, nor is it the memory area defined in the Java virtual machine specification; It's in jdk1 The new NIO introduced in 4 is an I/O mode based on channel and buffer. It can directly allocate out of heap memory using the Native function library, and then operate through a DirectByteBuffer object stored in the Java heap as a reference to this memory;


9. Remarks

Part of the content is excerpted from "deep understanding of Java virtual machine" - Zhou Zhiming (3rd Edition).

Keywords: Java jvm

Added by hubbardude on Thu, 17 Feb 2022 18:22:30 +0200