An overview of the

This article focuses on the JVM memory model, parsing the role and usage scenarios of the various runtime memory data areas.

The JVM models mentioned in this article are based on the JDK-1.8 version

JVM memory model

Runtime data area

Program Counter (Program Conunter Regisiter)

A program counter is a relatively small memory space that can be viewed as an indicator of the bytecode line number executed by the current thread. The essence is to record the order in which the bytecode is executed. An area that does not have any OutOfMemoryError cases in the Java Virtual Machine Specification.

JVM Stack

A virtual machine stack, which holds local variables inside a thread while it is running, can also be understood as a thread stack.

When each method is executed, the virtual machine creates a Stack Frame to store local variables, operand Stack, dynamic connections, method exits, and other information.

A Stack Frame is created when a method is called and destroyed when the method terminates (whether it completes normally or throws an exception).

Bytecode instruction analysis (describing JVM Stack operations)

public int add(a) {
  int a = 1;
  int b = 2;
  int c = b - a;
  return c;
}

0 iconst_1 // push a to the top of the local variable stack
1 istore_1 // Assign 1 to a
2 iconst_2 // push b to the top of the local variable stack
3 istore_2 // Assign b to 2
4 iload_2  // Read b into the operand stack
5 iload_1  // Read a into the operand stack
6 isub     // execute b-a
7 istore_3 // Store a value of type int into the local variable table 3
8 iload_3  // read c into the operand stack
9 ireturn  / / return
Copy the code

Local variable

The local variable table stores various compile-time Java virtual machine basic database types (Boolean, byte, CHAR, short, int, float, long, dubble) and object references (reference type, The real data of an object is usually stored in heap space.

The storage space in the local variable table is represented by variable slots, in which 64 bit long and double occupy two variable slots.

Operand stack

Each stack frame contains a first-in, first-out (FIFO) stack of operands. The depth of the stack of operands in the stack frame is determined by compile time and is saved and made available to the stack frame through the code property of the method.

Dynamic link

Each stack frame contains a reference to the run-time constant pool of the type of the current method. To dynamically link the code for the current method.

In a class file, a method that calls other methods or accesses local member variables needs synbolic references. Dynamic linking converts these symbolic references to direct references to the actual method.

Methods the export

Method completes normally, and the current stack frame restores the caller’s responsibilities, including restoring the caller’s local variable table, operand stack, and the correct program counter increment. Skip the method call instructions that were just executed, etc., and the code in low use will continue to execute normally after the method being called is pushed into the operand stack.

Method completes when some instruction causes the JVM to throw an exception, or the user displays a run through the thorw keyword, while catching no exceptions in the method. If the method exception call completes, there may not be a method return value returned to the caller.

Native Method Stack

The memory space allocated for native methods is used to service native keyword modification methods.

Native methods are mainly Java calls to C/C++ libraries.

Method Area

The main storage data are: constant, static variables, class information.

The method area holds the memory addresses of static variables. The method area has a meta space called permanent generation before JDK1.8.

Heap (Heap)

The largest chunk of memory managed by the JVM. An important concept related to the heap is the garbage collector. Almost all garbage collectors use a generational collection algorithm, so the memory space is divided accordingly based on this: new generation and old generation, and the new generation is divided into Eden space, From Survivor space, and To Survivor space.

During the creation of an object, the Eden region will first exist, and after minor GC, it will enter survivor, and after 15 survivor transitions, it will enter the old age.

If the JVM runs out of memory, the FULL GC will be triggered, and the JVM will throw OOM if the memory cannot be allocated after the second GC.

GC ROOT reachability analysis is used to analyze whether objects have references and are reclaimed.

Direact Memory

Direct memory, which is not managed by the JVM but by the operating system, is closely related to Java NIO. Java operates on direct memory through DirectByteBuffer.

JVM memory parameter Settings

Memory Parameter Configuration

JVM memory parameter setting format of spring-boot program (Tomcat startup directly in the bin directory catalina. sh file Settings)

java -Xms2048m -Xmx2048m  -Xmn1024 -Xss512k -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m -jar  xxx-xxx.jar
Copy the code

There are two JVM meta-spaces: -xx :MetaspaceSize=N and -xx :MaxMetaspaceSize=N. For 64-bit JVMS, the default meta-space is 21MB, and the default maximum meta-space is unlimited.

-xx :MaxMetaspaceSize: Sets the maximum value of the metasize space. The default value is -1, that is, it is not limited by the local memory size.

-xx :MetaspaceSize: specifies the initial size of the metasapace, in bytes. The default value is 21 MB. When this value is reached, the full GC is triggered for type uninstallation, and the collector adjusts this value. Lower the value if you free up a lot of space; If very little space is freed, increase this value appropriately, with no more than -xx :MaxMetaspaceSize (if set).

Since resizing the metaclass requires full GC, which is a very expensive operation, if a lot of full GC occurs during startup, it is usually due to a permanent generation or a metaclass resizing. In this case, It is generally recommended that the JVM parameter MaxMetaspaceSize and MetaspaceSize be set to the same value and larger than the initial value, which we usually set to 256M for 8GB of physical memory.

The heap space memory overflow

import java.util.ArrayList;
import java.util.List;

public class HeapOverFlowTest {

    byte[] a = new byte[1024 * 1024 * 2]; // 2mb

    public static void main(String[] args) {
        List<HeapOverFlowTest> list = new ArrayList<>();
        while(true) {
            list.add(newHeapOverFlowTest()); }}}// Output the result
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
	at cn.edu.cqvie.jvm.HeapOverFlowTest.<init>(HeapOverFlowTest.java:8)
	at cn.edu.cqvie.jvm.HeapOverFlowTest.main(HeapOverFlowTest.java:13)
Copy the code

The vm stack memory overflows

public class StackOverFlowTest {

    / / the JVM Settings
    // -xss128K, -xss default 1M
    static int count = 0;

    static void redo(a) {
        count++;
        redo();
    }

    public static void main(String[] args) {
        try {
            redo();
            System.out.println(count);
        } catch(Throwable t) { t.printStackTrace(); }}}// Output: stack overflow
java.lang.StackOverflowError
	at cn.edu.cqvie.jvm.StackOverFlowTest.redo(StackOverFlowTest.java:11)
	at cn.edu.cqvie.jvm.StackOverFlowTest.redo(StackOverFlowTest.java:11)
	at cn.edu.cqvie.jvm.StackOverFlowTest.redo(StackOverFlowTest.java:11)...Copy the code

Conclusion:

– The smaller the Xss setting, the smaller the count value, indicating that the number of stack frames allocated in a thread stack is smaller, but the larger the number of threads that can be opened for the JVM as a whole.

Method area memory overflow

  1. Note that in the 1.8 model, run-time constant pool data is put into the heap, so our limit on the size of the method area makes no sense for the run-time constant pool. They’re just going to selljava.lang.OutOfMemoryError: Java heap spaceThe exception.
  2. The following is an example of overflow simulation through the GCLib simulation method.
/** * -XX:MetaspaceSize=10m -XX:MaxMetaspaceSize=10m */
public class MyTest4 {

    public static void main(String[] args) {
        for(; ;) { Enhancer enhancer =new Enhancer();
            enhancer.setSuperclass(MyTest4.class);
            enhancer.setUseCache(false);
            enhancer.setCallback((MethodInterceptor) (obj, method, args1, proxy) ->
                    proxy.invoke(obj, args1));

            System.out.println("hello world"); enhancer.create(); }}}// Output the result
Caused by: java.lang.OutOfMemoryError: Metaspace
	at java.lang.ClassLoader.defineClass1(Native Method)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:756)...Copy the code

JVM Monitoring tool

VisualVM

VisualVM provides detailed information about Java applications running on the Java Virutal Machine (JVM). In the Graphical user interface of VisualVM, you can easily and quickly view information related to multiple Java applications.

The resources

  1. Deep Understanding of the Java Virtual Machine, 3rd edition, zhiming Zhou
  2. Java Virtual Machine specification (Java SE 8 edition), translated by Love Fly, Zhou Zhiming et al
  3. The VisualVM home page document
  4. Oracle official website Java VIRTUAL Machine specification