Detailed explanation of jvm (1)丨data area during jvm runtime

Beginning

Start writing JVM today. From this series of articles, you will be able to learn JVM memory distribution, garbage collection algorithm and garbage collection details, fault diagnosis methods, JVM class loading details, bytecode and APM system principles, as well as some related Scattered points such as the principle of reflection, etc. This series mainly focuses on troubleshooting, as well as GC and subsequent bytecode things, so although I will also talk about basic things, I won't talk about them in detail. I never write articles for beginners, I just want to Those who are learning basics or feel tired of learning can just click on the upper right corner to close it.

There will be more articles in this series, so I won’t make each article extremely long, which will make me tired and you tired too. But in order to let you learn systematically, each system will be discussed together as much as possible.

Just like my previous style, without further ado, let’s get started~

The data area of ​​jvm during operation generally includes heap, stack, method area, program counter, etc. Of course, this is a very abstract summary. There are many details in each place. Let’s look at them one by one.

1. Program counter (also called PC register)

This thing is a line number indicator that records the bytecode executed by the current thread. In other words, it records which line of bytecode the current thread has executed. This thing has several features:

  1. Thread private

  2. The memory occupied is very small and OutOfMemoryError will not occur.

  3. If the native method is executed, the value here is empty, that is, undiffed. The above three points are easy to understand. Let’s explain them one by one. The first point is that JVM's multi-threading is implemented by switching threads in turn and allocating processor execution time. That is to say, a processor core will only execute one thread at the same time, and the processor will not record when switching threads. Where did the previous thread execute, so in order to be able to return to the original position after thread switching, each thread needs to have its own independent program counter. Second point, since it only stores a number or is undiffed, it certainly won't take up much space, and it won't be unable to store the number because it's too long, so there's no possibility of memory overflow. The third point is that we know that most of Java's native methods are implemented in C and are not compiled into bytecode instructions that need to be executed. Therefore, if the execution method is a native method, there is no need to store a value here.

2. Stack

The jvm stack is a thread memory model that describes the execution of Java methods. It is private to the thread and has the same life cycle as the thread. The stack is composed of stack frames one by one, and the stack frame is mainly composed of four parts, namely the local variable table, the operand stack, the dynamic link, and the return address. The structure diagram of the stack is as follows:

Let’s talk about them one by one:

  1. The local variable table is used to store the parameters of the method and the local variables defined within the method. The smallest unit is the variable slot. Each variable slot can store a basic data type (except long and double), the reference and return address of the object. The data.

  2. During the execution of the operand stack method, there will be various bytecode instructions to write and extract content from the operand stack, that is, pop and push operations (similar to the stack frame operation in the Java stack).

  3. Dynamic linking Saves a reference to the method to which the stack frame belongs in the runtime constant pool to support dynamic linking during method calls.

  4. The return address refers to the place where the current method is called, because after the method is executed, you have to know where to continue execution.

上面的概念可能比较生涩,但是别担心,我后边还会回头来说这些东西的,这节我们先混个脸熟

3. pile

The heap is a memory area shared by all threads and is created when the virtual machine starts. This area is used to store object instances, and almost all object instances allocate memory here. The heap is the main area managed by the Java garbage collector (GC heap), and the garbage collector implements automatic destruction of objects. The Java heap can be subdivided into: new generation and old generation; more detailed ones include Eden space, From Survivor space, To Survivor space, etc. The Java heap can be in physically discontinuous memory space, as long as it is logically continuous, just like our disk space. Can be controlled via -Xmx and -Xms.

4. Method area

This area is used to store loaded class information, constants, static variables, and just-in-time compiled code cache. One thing worth mentioning here is that the term method area actually appears in the JVM specification. Before 1.8, the corresponding implementation of the method area was the permanent generation. After 1.8, hotspot has replaced the permanent generation with metaspace because of this It can reduce the chance of OOM occurring.

5. Runtime constant pool and string constant pool

The runtime constant pool was placed in the permanent generation before 1.7, and after 1.8 it was placed in the heap memory. Here is the cache used to store basic types of wrapper classes (Integer -128 to 127), as well as string values. Some people may also know the class constant pool. What needs to be emphasized here is that these two are not the same thing. We will also talk about the class constant pool later, so it doesn’t matter if you don’t understand it here.

The string constant pool is used to store strings that have been created.

Since the string constant pool will not be explained in detail later, in a responsible manner, I will talk more about it here. We must have seen the following code:

public static void main(String[] args){
        String str = "ABC"
        String str1 = "ABC"
        String str2 = new String("ABC")
        String str3 = null

        System.out.println(str==str1)
        System.out.println(str==str2)
        str3 = str2.intern()
        System.out.println(str==str3)
   }

I won’t be too careful. The output here is shown in the picture below:

Let's explain it bit by bit. The str in the first sentence is in the constant pool of the class during compilation. After the code executes this sentence, "ABC" will be thrown into the string constant pool, and then str points to the constant. "ABC" of the pool (you just care that it will be thrown into the constant pool after execution, which will be discussed later in the class constant pool). In the second sentence, it is found that "ABC" already exists in the string constant pool, so directly Just let str1 point directly to "ABC" in the constant pool. Since the new instruction is used in the third sentence, it will not search in the constant pool. Instead, it will open up a new space on the heap memory to create a "ABC" again. ABC", the fourth sentence is skipped. Five or six sentences are very simple. The fifth sentence outputs true, the sixth sentence outputs false, and in the seventh sentence you need to know that the intern method will copy the called string into the constant pool and return a reference to the constant pool, but if If there is already the same string in the constant pool, the string reference is returned directly, so the eighth sentence outputs true. Note that it is copied. In order to prove that it is copied in instead of thrown in directly, let's look at another piece of code here:

public static void main(String[] args){
        String str2 = new String("ABC")
        String str3 = null

        str3 = str2.intern()
        System.out.println(str2==str3)
}

The output result is as follows, which is in line with expectations. If you don’t understand, you can understand the above words.

6. Direct memory

This area is not part of the jvm, but it is actually a very important part. After Java has NIO, it can directly operate off-heap memory. The advantage of this is that it avoids copying data back and forth between the Java heap and the computer's native memory, which significantly improves performance. However, the side effect is that improper use can also cause OOM. (Because it is also limited by physical memory).

Guess you like

Origin blog.csdn.net/weixin_54542328/article/details/134875249