Java runtime memory management

I. Introduction

I hope that when we usually develop and write code, we can know how the memory is allocated for the code currently written.
We know that a Java programmer does not need to worry about the release of memory at all, but relies on the JVM to manage it. When writing C++ code before, he must always remember that the new space should be released in time, otherwise the program will easily appear. Out of memory situation. Because Java is indeed a lot more convenient in this regard, allowing us to have more energy to consider the implementation of business aspects. However, this does not mean that we can use memory unscrupulously, because:

1. JVM will not clean up memory in time
2. We cannot control JVM to clean up memory through code

This requires us to understand the garbage collection mechanism of the JVM and arrange memory reasonably during the development process. So how can we arrange the memory reasonably? Then we need to understand the memory allocation mechanism of the JVM, and then we can really control it and let the program run under our applause.

Two, JVM memory model

Usually we have a rough concept of Java memory, which is to divide the heap and stack, but in fact it is much more complicated. The complete memory model is given below: the
insert image description here
content of the corresponding area is:
insert image description here

insert image description here

program counter PC

In this area, I have summarized the following key points:

1. There will be no OOM (Out Of Memory) errors in this area
2. It is private to the thread, because each thread has its own program counter to indicate the bytecode line number executed by the current thread
3. Identify Java The bytecode address of the method, not the Native method
4. On the CPU, we cannot directly operate this area

virtual machine stack

This area is also the stack of the stack we usually talk about. There are the following points about this block area:

1. It is private to the thread and has the same life cycle as the thread
2. When each java method is executed, this area will generate a stack frame
3. The local variables stored in the stack frame have 8 basic data types and reference types ( The memory address of the object)
4. The running process of the java method is the process of pushing and popping the stack frame in the virtual machine stack
5. When the depth of the stack requested by the thread exceeds the depth allowed by the virtual machine stack, a StackOverFlow will be thrown Error
6. When the Java virtual machine dynamically expands to the point where it cannot apply for enough memory, an OutOfMemory error will be thrown

native method stack

This area is thread-private. As the name suggests, it is different from the virtual machine stack. It is used to process Native methods (Java native methods), while the virtual machine stack is used to process Java methods. For native methods, there are many native methods in Object, such as hashCode, wait, etc., and the execution of these methods is often carried out by means of the operating system.

This area may also throw StackOverFlowError and OutOfMemoryError

Java heap

He is the area we talk about the most and pay the most attention to. Our later performance optimization is mainly aimed at this part of memory, the main battlefield of GC, where almost all object instances and array data are stored. What is allocated in the virtual machine stack is only references, and these references will point to the objects actually stored in the heap. Here I have roughly summarized as follows:

1. The Java heap belongs to the thread shared area, and all threads share this memory area.
2. From the perspective of memory recovery, the Java heap can be divided into the new generation and the old generation, which can reclaim memory faster.
3. From the perspective of memory allocation , The Java heap can be divided into a thread-private allocation buffer (Thread Local Allocation Buffer, TLAB), which can allocate memory faster 4. When the
Java virtual machine dynamically expands to the point where it cannot apply for enough memory, an OutOfMemory error will be thrown

method area

The method area mainly stores data such as class information, constants, static variables, and code compiled by the compiler that have been loaded by the virtual machine. GC is relatively rare in this area. A summary is as follows:

1. The method area belongs to the thread sharing area
2. It is habitually called permanent generation
3. Garbage collection rarely patronizes this area, but it also needs to be recycled, mainly for the constant pool recovery, type unloading
4. The constant pool is used to store the generation generated during compilation Various bytecodes and symbol references, the constant pool has certain dynamics, which can store constants generated during compilation. 5. Constants
during runtime can also be added to the constant pool, such as the intern() method of string.

runtime constant pool

The runtime constant pool is also part of the method area, which is used to store various literal and symbolic references generated by the compiler. Let me explain it separately, because we usually use String to compare prices, which involves this piece of knowledge, but this area will not throw OutOfMemoryError

3. Garbage Marking Algorithm

Garbage Collection (Garbage Collection), often referred to as GC. GC mainly does two jobs:

  • memory division and allocation,
  • Recycle the garbage.

Regarding the division and allocation of memory, the current division of Java virtual machine memory depends on the design of GC. For example, GC now uses the generational collection algorithm to collect garbage. The Java heap, as the main area managed by GC, is subdivided into The new generation and the old generation, and the new generation can be divided into Eden space, From Survivor space, To Survivor space, etc. in more detail. This division is for faster memory allocation and recycling. After space division, GC can allocate memory space for new objects. Regarding garbage collection, the referenced object is a living object, and the unreferenced object is a dead object (that is, garbage). The GC must distinguish between a living object and a dead object (that is, a garbage mark), and Recycle the garbage.

Before recycling the garbage, the GC must first mark the garbage, so how to mark it? There are currently two garbage marking algorithms:

  • reference counting algorithm
  • root search algorithm

1. Reference counting algorithm:

​ The basic idea of ​​the reference counting algorithm is that each object has a reference counter. When the object is referenced somewhere, its reference counter is incremented by 1, and decremented by 1 when the reference becomes invalid. When the value in the reference counter becomes 0, the object cannot be used and becomes garbage.

​ At present, the mainstream Java virtual machine does not choose the reference counting algorithm to mark garbage. The main reason is that the reference counting algorithm does not solve the problem of circular references between objects. For example, in the comment 1 and comment 2 of the following code, tom and mike refer to each other, and there is no other reference to these two objects. In fact, these two objects are dead and should be collected as garbage, but Since these two objects refer to each other, the reference count will not be 0. If the Java virtual machine uses a reference counting algorithm, the garbage collector cannot reclaim them.

class Student {
    
    
    Student friend;
}
//
Student s1 = new Student();
Student s2 = new Student();
s1.friend = s2;// 1
s2.friend = s1;// 2

s1 = null;
s2 = null;

优点:
The reference counting collector can be executed very quickly and interleaved in the running of the program. It is more beneficial to the real-time environment where the program needs not to be interrupted for a long time.

缺点:
Unable to detect circular references. If the parent object has a reference to the child object, the child object in turn references the parent object. This way, their reference count can never be 0.

2. Root search algorithm

​ The basic idea of ​​this algorithm is to select some objects as GC Roots and form a set of root objects, and then use these GC Roots objects as the starting point to search downwards. If the target object is connected to GC Roots, we call it the The target object is reachable. If the target object is unreachable, it means that the target object can be recycled, as shown in the figure below.

insert image description here

As can be seen from the figure above, ObjF, ObjD, and ObjE are all unreachable objects. Although ObjD and ObjE refer to each other, they are still judged as recyclable objects because they are unreachable to GC Roots. The root search algorithm solves the problem that the reference counting algorithm cannot solve: dead objects cannot be recycled because they refer to each other.

4. JVM memory source code example description

package senduo.com.memory.allocate;

/**
 * *****************************************************************
 * * 文件作者:ouyangshengduo
 * * 创建时间:2017/8/11
 * * 文件描述:内存分配调用过程演示代码
 * * 修改历史:2017/8/11 9:39*************************************
 **/
public class MemoryAllocateDemo {
    
    
    public static void main(String[] args){
    
     //JVM自动寻找main方法
        /**
         * 执行第一句代码,创建一个Test实例test,在栈中分配一块内存,存放一个指向堆区实例对象的指针
         */
        Test test = new Test();
        
        /**
         * 执行第二句代码,声明定义一个int型变量(8种基本数据类型),在栈区直接分配一块内存存储这个变量的值
         */
        int date = 9;
        
        /**
         * 执行第三句代码,创建一个BirthDate实例bd1,在栈中分配一块内存,存放一个指向堆区实例对象的指针
         */
        BirthDate bd1 = new BirthDate(13,6,1991);
        
        /**
         * 执行第四句代码,创建一个BirthDate实例bd2,在栈中分配一块内存,存放一个指向堆区实例对象的指针
         */
        BirthDate bd2 = new BirthDate(30,4,1991);
        
        /**
         * 执行第五句代码,方法test1入栈帧,执行完出栈
         */
        test.test1(date);
        
        /**
         * 执行第六句代码,方法test2入栈帧,执行完出栈
         */
        test.test2(bd1);
        
        /**
         * 执行第七句代码,方法test3入栈帧,执行完出栈
         */
        test.test3(bd2);

    }
}

reference

Guess you like

Origin blog.csdn.net/daokedream/article/details/130293131