Preface:
Hello, good morning, afternoon, afternoon, evening. I am Java2B. A 985, everyday 996 engineer. Aren’t you very excited?
Brother 2B continues to teach you about JVM today. This chapter is: previous article: CMS collector and GC log analysis location problem detailed solution juejin.cn/post/684490…
JVM virtual machine CMS and G1 collector details juejin.cn/post/684490…
What is the JVM
I believe many partners are very familiar with the JVM is not a virtual machine? What about virtual machines? It’s the JVM! This is nonsense.
The JVM can say both familiar and unfamiliar from us, a lot of friends may not work in contact with the technology, but in interviews are often asked (probability is pretty big), was asked to from recognize unlucky, rote learning is useless, it ends up being forgotten, but it doesn’t matter. You met 2 b elder brother I today, I said the free for everyone said the JVM knowledge, If I don’t make it clear to you that I lose, you can leave a comment on me, and if you can, can you give me a thumbs up? Stop the ink and get on with it.
Ok, loading. There should be flowers here! ❀ ❀ ❀ ❀ ❀ ❀ ❀ ❀
I met the JVM:
I believe this diagram is familiar to everyone, this is the entire Java system, including JDK.JRE.JVM three relations.
You can see that the JRE contains the JVM and the JDK contains the JRE.
The JDK is the grandfather, the JRE is the father, and the JVM is the son (if the example is not appropriate)
Let’s look at the code:
public class App { private String name; private Object object = new Object(); /*** ** / public intadd() {
int a = 1;
int b = 2;
int c = (a + b) * 100;
returnc; } /** * public static void main(String[] args) throws InterruptedException {App App = new App(); int result = app.add(); System.out.println(result); }}Copy the code
When we run the above code, the output result is 300. Although the code is very simple, this time has involved the knowledge of JVM. When we learn the foundation of Java, the teacher told us that Java is cross-platform and runs everywhere at one time.
So how does Java go cross-platform? Continue with the image below:
As you can see from this figure, the compiled app. class file can run in Windows or Linux, but the underlying operation instructions of the two systems are different. In order to shield the details of the underlying instructions and play a cross-platform role, THE JVM has played an important role. We often say Java is cross-platform rather than Jvm cross-platform (JRE runtime cross-platform). How can a Jvm be cross-platform?
JVM underlying principles:
The underlying JVM consists of three systems: class loading, runtime data area, and execution engine.
We’ll focus on the JVM runtime data area (stack) today, but the other two pieces will focus on my previous and subsequent articles.
Our app.class file is loaded into memory (run time data area) by reading files from hard disk through the class loading subsystem.
What happens after it’s loaded? (It’s a metaphor for people to eat “eat into the stomach”, each organ is responsible for its own work and absorption)
Stack Stack:
Let’s start with one area of memory: the virtual stack. As we all know, a stack is a data structure and a thread-specific area, meaning that each thread has its own stack area. We run app.java and output 300 results based on thread execution. Which thread is executing? Get thread snapshot: “main thread”
Stack “data structure” storage content “FILO first and then out
We all know that each method has its own local variables, such as result (main) and a, B, and C (add). So the Java virtual machine allocates a separate stack frame memory area for each method to distinguish the memory area within the scope of local variables. Let’s try to sketch the memory activity of the code as shown above.
The first line of code that executes main allocates the stack frame for main() and stores the math local variable, and then executes add(), which in turn allocates the stack frame area for Add ().
The stack here stores data in the same way as the stack learned in the data structure, first in, then out. When the add() method is finished, it is released from the stack, which is in accordance with the characteristics of the first-in-last-out method.
The stack frame:
The internal “data structure” of stack frame is mainly composed of the following parts: local variable table, operand stack, method exit and other information.
After all, what does stack frame do? Before we get to that, we get to the underlying principle of bytecode. Let’s take a look at the bytecode file of our code above.
The app.class file looks like garbled code, but it actually has a corresponding meaning. Oracle has a special JVM bytecode instruction manual to check the corresponding meaning of each set of instructions. So that’s not what we’re looking at, of course.
The JDK comes with a javap command that generates the above class file into a more readable bytecode file.
Compiled from "App.java"
public com.App {
public com.App();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."
":()V
4: aload_0
5: new #2 // class java/lang/Object
8: dup
9: invokespecial #1 // Method java/lang/Object."
":()V
12: putfield #3 // Field object:Ljava/lang/Object;
15: return
public int add();
Code:
0: iconst_1
1: istore_1
2: iconst_2
3: istore_2
4: iload_1
5: iload_2
6: iadd
7: bipush 100
9: imul
10: istore_3
11: iload_3
12: ireturn
public static void main(java.lang.String[]) throws java.lang.InterruptedException;
Code:
0: new #4 // class com/App
3: dup
4: invokespecial #5 // Method "
":()V
7: astore_1
8: aload_1
9: invokevirtual #6 // Method add:()I
12: istore_2
13: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
16: iload_2
17: invokevirtual #8 // Method java/io/PrintStream.println:(I)V
20: return
}
Copy the code
At this point, the JVM instruction code is much clearer, and the general structure is readable: classes, static variables, constructors, add() methods, main() methods. The instructions in the method are still a bit confusing, so let’s use the add() method:
Code:
0: iconst_1
1: istore_1
2: iconst_2
3: istore_2
4: iload_1
5: iload_2
6: iadd
7: bipush 100
9: imul
10: istore_3
11: iload_3
12: iretu
Copy the code
These lines of code are the corresponding four lines in our add() method. Everyone knows that the lower the code, the more lines the code will implement, because it will contain some of the details that Java code hides at runtime. So the same, this JVM instruction is also the official manual can be consulted, there are many translation versions on the Internet, if you want to know about their own baidu.
Execution process:
The meanings of some instructions in the design code:
Step 1: Stack pressing:
Push the int constant 1 onto the operand stack
0: iconst_1 pushes 1 onto the operand stack
Step 2: Storage:
Store a value of int to the local variable 1
1: istore_1 local variable 1, which in our code is the first local variable A, first allocates memory to A in the local variable table, and then stores the value of int, which is the only 1 so far, into local variable A
Step 3: Assign
These two lines of code are similar to the first two.
2: iconst_2 3: istore_2 Copy the code
Step 4: Loading:
Loads a value of type int from local variable 2
4: iloAD_1 5: iload_2 These two codes load the values of local variables 1 and 2, i.e. a and b, into the operand stack
Step 5: Add
Performs an addition of int type
As soon as the iadd command is executed, it pops 1 and 2 from the bottom of the operand stack and adds them, then pushes the result 3 to the bottom of the operand stack.
Step 6: Stack pressing:
Pushes an 8-bit signed integer onto the stack
7: Bipush 100 This instruction pushes 100 onto the stack
Step 7: Multiplication:
Perform multiplication of type int
9: imul here is similar to the above addition, pop 3 and 100 on the stack, push the result 300 on the stack
Step 8: Stack pressing:
The value of int type is stored in the local variable 3
10: istore_3, which I’m sure you’re familiar with, is the same thing as step 2 and step 3, where you put 300 in the local variable 3, which is C
Step 9: Loading:
Loads int values from local variable 3
11: ILOAD_3 is loaded into the operand stack from local table variable 3
Step 10: Return to:
Returns a value of type int
12: ireturn
The add method is called from the main method, so the result variable is returned to the mian method through the method exit. So we know that we should go back to the third line of main() when main() calls add(), the method exit in the add() stack frame stores the location we’re going back to, so when add() is done, Returns to the corresponding location of the main() method based on information stored in the method exit. Look at the red line in my diagram
Stack stack relationship:
The main method has an app variable in addition to the result variable, which refers to an object. How is that object stored? Table structure: primitive type and reference type (Java called reference C, C++ called pointer)
Relationships are:
Reference the APP object in the heap by referring to the APP variable in the stack
Conclusion:
At this point, I believe you are familiar with the principle of JVM stack execution. Feel free to like and comment if you like it. The original is not easy to
If you think the author’s article is good, welcome to follow my wechat :Java2B(a daily 996 engineer).
Correction: The gray background “operand stack” should be changed to “local variable table” during process execution.