JVM runtime data area (based on JDK8, combined with bytecode and your own understanding)

JVM and concurrency and Java are two advanced topics. Today I will talk about a part of the JVM composition. It is also the JVM runtime data area that is most closely related to our daily work.
Let's take a look at the overall structure of the JVM:
JVM composition
the source files we write go through a compiler (such as the Javac compiler, the Java virtual machine is also cross-platform, and other languages ​​such as JRuby and other languages ​​can be sourced to bytes by the compiler of their own language Code compilation) After compiling into a Class file that stores bytecode, the subsequent work is taken over by the Java virtual machine. The class loading subsystem loads the data describing the class from the Class file to the method area of ​​the runtime data area (metaspace after JDK1.8), and verifies, converts, analyzes, and initializes the data, and finally can be formed directly by the virtual machine. The type of Java used. When executing Java code, the execution engine may have two options: interpreted execution (through the interpreter) and compiled execution (through the JIT instant compiler), or both, and may even include several different levels of compilers. Execution engine (in addition to interpreter and just-in-time compiler, there may be pre-compiler), execution engine will also start daemon thread for garbage collection when JVM is running.
After introducing the general process, return to our topic this time-runtime data area:

Virtual machine stack (corresponding to the stack area of ​​the runtime data area in the example diagram): The
virtual machine stack is a LIFO last-in-first-out stack structure implementation. A Java thread corresponds to a virtual machine stack memory structure. The virtual machine stack describes It is the memory model of Java method execution: each method will create a stack frame for storing local variable table, operand stack, dynamic connection and method exit, etc. It corresponds to a stack frame in the virtual machine stack from the stack to the stack. The virtual machine stack releases memory space as threads are destroyed, so no garbage collection management is required. However, if the method call depth is deep, such as recursive calls, it may cause insufficient stack depth and a StackOverflowError. You can adjust the stack size through the -Xss parameter.
Let's talk about each part of the stack frame in detail:
1.1 Local Variable Table (Local Variable Table) is a set of variable value storage space, used to store method parameters and local variables defined within the method, such as various basic types, object references and returnAddress . We can view the local variable table corresponding to each method in the Class file through the jclasslib plugin, as shown below:
Insert picture description here
For method1, we can see from the red circle that there are 3 local variable tables, which are this, length, num, length and num is our custom variable name, and what is this? In fact, this this is a variable that points to the current instance object. We can use this keyword in the instance method because the virtual machine helped us put the variable in the local variable table, and if it is a static modified class method, its local There is no this local variable in the variable table, and we cannot use this in class methods to refer to the current instance object. Interested friends can use the jclasslib plugin to observe the local variable table of the static method.
1.2 Operand stack(Operand Stack) is also often referred to as the operation stack, it is also a LIFO stack. JVM instructions are basically a stack-based instruction set architecture (comparable to the general physical machine's register-based instruction set architecture). Most of the instructions in the instruction stream are zero-address instructions. They rely on the operand stack for work. For example, we perform a simple int type addition, as shown below: The
Insert picture description here
iconst_1 instruction pushes the int type constant 1 onto the operand stack, the istore_1 instruction stores the int type value in the local variable 1, iconst_2 and istore_2 are similar, and the constant 2 is pushed into the operation Count the stack and then take the constant 2 at the top of the stack and store it in the local variable 2. The method call instruction in Java is also similar. For example, the aload 4 instruction on line 17 of the byte code is to push the local variable 4 (operandStack object) to the top of the stack, and the invokevirtual instruction on the line 19 of the byte code calls the virtual method, which is run according to the class of the object To call instance methods, which is also part of the bytecode implementation of the polymorphic mechanism in Java.
1.3 Dynamic Linking (Dynamic Linking) is a reference in the stack frame to the method of the stack frame in the runtime constant pool. This reference is held to support dynamic linking during the method invocation (Dynamic Linking). On the 19th line of the bytecode in the example picture of the operand stack, we can see that there is a # 4 after invokevirtual. This # 4 is a symbol reference to the method in the constant pool in the Class file structure. If the method is a non-virtual method, such as static Modified class methods (corresponding to invokestatic instructions), private modified private methods (corresponding to invokespecial instructions), because non-virtual methods will not have polymorphic choices, so these symbol references can determine the specific version of the method in the compiler, and Virtual methods, such as general instance methods, require the specific version of the method to be determined at runtime. This part is called dynamic linking.
1.4 The method exit (returnaddress) may store the value of the program counter that called the method. The method may have normal exit or abnormal exit, but both require a method exit to determine what to do after the method exits, and where to start executing the method The returned bytecode instruction.

Second, the local method stack: the
local method stack is used to manage the calling of Native local methods, and is private to the thread. The Native method is implemented in C or C ++ language. It is generally a platform-related implementation, and it is generally more efficient. The engine needs to load the local method library when executing the natvie method.

Third, the program counter (corresponding to the PC register in the runtime data area): the
program counter is also called the PC register, which can be regarded as the line number indicator of the bytecode executed by the current thread. We can analogize a register in the CPU also called the program counter. The program counter in the CPU saves the instruction address. The controller of the CPU reads the instruction from the memory according to the value of the program counter to decode and execute it. The program counter determines this program Process. The program counter in the JVM runtime data area is also a similar function. In the conceptual model of the virtual machine, the bytecode interpreter works by changing this counter to select the next bytecode instruction to be executed, branch, loop, Basic functions such as jumps, exception handling, and thread recovery need to rely on this counter to complete.
The program counter is also thread-private. When Java multithreading uses the same CPU core to achieve concurrency, to restore the correct execution position after thread switching, each thread must have an independent counter for recording the bytes executed by the current thread. The line number of the code instruction. The red number on the left side of the bytecode instruction in the example diagram describing the operand stack is the line number of the bytecode instruction.

Fourth, the Java heap: The
Java heap (Java Heap) is a memory area shared by all JVM threads, created when the virtual machine starts, all objects and arrays are allocated in the runtime data area. The heap space is recovered by an automatic garbage collection system, without the need for programmers to allocate and recycle memory. The heap space can be a fixed size or can be expanded, we can set the initial and maximum heap memory through -Xms and -Xmx, it is generally recommended to set the same. If there is no memory in the heap to complete the memory allocation of the instance object, and the heap can no longer expand, OutOfMemoryError will be thrown.

Fifth, the method area: The
method area (Method Area) is also a memory area shared by all JVM threads, created when the virtual machine is started, used to store the type information, constants, static variables, even the compiler (JIT ) The compiled code cache and other data. Before JDK1.8, HotSpot used the permanent generation to implement the method area. This design is prone to encounter permanent generation overflow problems. After JDK1.8, it began to use the meta space to implement the method area. If the method area cannot meet the new memory allocation requirements, an OOM exception will be thrown, such as applications that often dynamically generate a large number of Classes, including CGLib bytecode enhancements and a large number of JSPs.
Any shortcomings, please correct me, thank you.
If you feel rewarded, please give a compliment, thank you!

Published 14 original articles · praised 3 · visits 929

Guess you like

Origin blog.csdn.net/sjz88888/article/details/104864256