This is the 10th day of my participation in the August More text Challenge. For details, see: August More Text Challenge

During the execution of Java programs, the Java Virtual Machine divides the memory it manages into several different data areas. These zones have their own purposes and creation and destruction times. Some zones exist with the start of the virtual machine process, while others are created and destroyed depending on the start and end of user threads. According to the Java Virtual Machine Specification, the memory managed by the Java virtual Machine will include the following runtime data areas, as shown in the following figure:

Program counter

A Program Counter Register is a small piece of memory that can be seen as an indicator of the line number of bytecode executed by the current thread. The bytecode interpreter works by changing the value of this counter to select the next bytecode instruction to execute. It is an indicator of the program’s control flow. Basic functions such as branching, loop, jump, exception handling, and thread recovery depend on this counter.

Because multithreading in the Java Virtual Machine is implemented by switching between threads in turn, allocating processor execution time, at any given time, a processor (or, in the case of multi-core processors, a core) will execute instructions from only one thread. Therefore, in order to return to the correct execution location after a thread switch, each thread needs to have a separate program counter. The counters of each thread do not affect each other and are stored independently. We call this type of memory “thread private” memory.

This memory region is the only region where no OutOfMemoryError condition is specified in the Java Virtual Machine Specification.

Java virtual machine stack

Like program counters, the Java Virtual Machine Stack is thread-private and has the same life cycle as the thread. The virtual machine Stack describes the thread memory model for Java method execution: When each method is executed, the Java VIRTUAL machine synchronously creates a Stack Frame to store information about local variables, operand Stack, dynamic connections, method exits, and so on. Each method that is called until the end of the execution corresponds to a stack frame in the virtual machine stack from the stack to the stack.

This memory region specifies two types of exception conditions: a StackOverflowError is thrown if a thread requests a stack depth greater than allowed by the virtual machine; If the Java virtual machine stack size can be dynamically expanded, an OutOfMemoryError will be thrown when the stack cannot be allocated enough memory.

# Each thread can use memory
-Xss256K
Copy the code

Local method stack

Native Method Stacks are very similar to virtual machine Stacks, except that the virtual machine stack performs Java Method (bytecode) services for virtual machines, and the Native Method stack serves Native methods used by virtual machines.

The Java Virtual Machine Specification does not impose any rules on the language, usage mode, and data structure of methods in the local method stack, so specific virtual machines are free to implement it as needed. Some Java virtual machines (such as hot-Spot Virtual machines) even combine the local method stack with the virtual machine stack. Like the virtual machine stack, the local method stack throws StackOverflowError and OutOfMemoryError, respectively, when the stack depth overflows or when the stack expansion fails.

The Java heap

The Java heap is an area of memory shared by all threads and created when the virtual machine starts. The sole purpose of this memory area is to hold object instances, and “almost” all object instances in the Java world are allocated memory here. Even with the improvement of compile counting, especially the power of escape analysis, the optimization of stack allocation and scalar substitution means that Java object instances are not allocated entirely on the heap.

The Java heap can be in a physically discontinuous memory space, but logically it should be treated as continuous. The Java heap can be implemented as either fixed size or extensible, but the current mainstream Java virtual machine is implemented as extensible (with the -xmx and -xMS parameters). The Java VIRTUAL Machine will throw an OutOfMemoryError if there is no memory in the Java heap for instance allocation and the heap is no longer growing.

# Maximum, minimum, New Generation
-Xmx512M, -xms512m, and -xmn128m
Copy the code

Methods area

The Method Area, like the Java heap, is a memory Area shared by all threads. It is used to store data such as type information loaded by the virtual machine, constants, static variables, and code cache compiled by the real-time compiler.

It is true that garbage collection is relatively rare in this area, but it is not that the data enters the method area as “permanent” as the name of the permanent generation. The target of memory reclamation in this region is mainly for constant pool reclamation and type unloading. Generally speaking, the effect of reclamation in this region is relatively difficult to be satisfied, especially for type unloading, the conditions are quite harsh, but sometimes the reclamation in this part of the region is indeed necessary.

An OutOfMemoryError is thrown if the method area does not meet the new memory allocation requirements.

# Maximum and minimum values
-XX:MaxPermSize = 128 m, - XX: PermSize = 64 m
Copy the code

Runtime constant pool

The Runtime Constant Pool is part of the method area. In addition to the Class version, field, method, interface, and other description information, there is also a Constant Pool Table, which is used to store the various literal and symbolic references generated at compile time, this part of the content will be stored in the method area of the runtime Constant Pool.

Metadata area

The metadata area replaces version 1.7 and previous permanent generations. Both the metadata area and the permanent generation are essentially implementations of the method area. The method area stores the class information, static variables, constants and other data loaded by the VM.

# Maximum minimum
-XX:MetaspaceSize=8m 
-XX:MaxMetaspaceSize=50m
Copy the code

Direct memory

Non-virtual machine running part of the data area, the use of Native libraries can be directly allocated out of the heap memory, limited by the total local memory size and processor addressing space.

# Direct memory size
-XX:MaxDirectMemorySize=128M
Copy the code

Practical: OutOfMemoryError&StackOverflowError

Stack overflow

The VM options configuration is as follows: -verbose: gc-xms20m-XMx20m-xmn10M -xx :+PrintGCDetails -xx :SurvivorRatio=8

public class OOMTest {


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

}

运行结果:
  Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
	at java.util.Arrays.copyOf(Arrays.java:3210)
	at java.util.Arrays.copyOf(Arrays.java:3181)
	at java.util.ArrayList.grow(ArrayList.java:265)
	at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:239)
	at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:231)
	at java.util.ArrayList.add(ArrayList.java:462)
	at com.miracle.jvm.OOMTest.main(OOMTest.java:18)

Copy the code

The VM stack and local method stack overflow

The VM options: – Xss256k

public class JavaVMStackOverFlow {

    private int stackLength = 1;

    public void stackLeak(a) {
        stackLength++;
        stackLeak();
    }

    public static void main(String[] args) {
        JavaVMStackOverFlow overFlow = new JavaVMStackOverFlow();
        try {

            overFlow.stackLeak();
        } catch (Exception e) {
            System.out.println("stack length: " + overFlow.stackLength);
            throw e;
        }
    }
}

运行结果:
Exception in thread "main" java.lang.StackOverflowError
	at com.miracle.jvm.JavaVMStackOverFlow.stackLeak(JavaVMStackOverFlow.java:15)
Copy the code