JAVA interview --- sprint through the code in-depth understanding of JVM --- (To be continued)

Author statement: original, please indicate the source! To be continued at present, we will continue to update

First, what is the JVM

JVM is an acronym for Java Virtual Machine (Java virtual machine). Since it is a virtual machine, you need to build on top of the operating system. JVM there are many, is currently the most widely used is HOTSPOT, this paper is concerned HOTSPOT virtual machine, so the next JVM are HOTSPOT.

Two, JAVA operating mechanism

Figure 1.java operating mechanism
We can see from the figure, java has been able to operate our CPU to calculate, in fact, dealing with the JVM and CPU, and can support JVM encoding format, that is, .class files (bytecode file). We all know that because of JVM JAVA made for cross-platform language, we can see from the figure, as long as the compiler process .class file, so the language can run on the JVM, so we said, JVM is cross-language platform. As long as the byte code file specification can be received JVM. Also be able to run up on the JVM.

Three, JVM Chart

jvm Chart Overview
From the figure, we can clearly see that we get the byte code files in the JVM, the class is first loaded into the Class file subsystem, then we run into the data area, the last byte code file execution engine converted to machine instructions, interacting with the CPU.

Fourth, the class loader subsystem

Class loader subsystem architecture of FIG.

1, action class loader subsystem

Class loader subsystem is used to load Class file byte code at the beginning of our file has a specific CA FE BA BE bytecode header identification. ClassLoader only responsible for loading the Class, as can run is determined by our execution engine to decide. Loaded class information stored in the method area, the method of storage area while back our runtime constant pool information.

2, Load (Loading)

Loading refers to the class of the read class files into memory, i.e. create a java.lang.Class object into the memory, as the access method entry area of ​​various data class. We can easily see, the role is to load static binary byte streamer drive our runtime data structures.

3, the link (Linking)

3.1 verification (Verify)

Verify the name suggests, aims to verify information Class byte stream file conforms to the requirements of the current virtual machine, ensure the accuracy and security of load classes. Protection JVM itself will not be affected.

Verification process includes four authentication:
file format validation, metadata validation, bytecode verification, verification of symbolic references.

3.2 Preparation (Prepare)

Allocate memory for the preparation stage static class variables, i.e., the initial value and set the default value of zero (0 numeric type character type empty).
Note: 1, the preparatory stage will not assign a static variable contains the final, because with a final static variables at compile time it has been assigned.
2, instance variables can not be assigned here, along with the instance variable is assigned to java objects heap.

3.3 Analytical (Resolve)

Resolved the most important point is that the symbolic constant pool references converted to a direct reference.
Symbolic references: Symbol reference is to target a set of symbols to describe quoted, literal symbols can be literally any form, as long as the conflict does not appear to be able to locate the line. Independent of layout and memory.
Direct reference: is a pointer to the target, or can be positioned directly offset handle.
We can look at a piece of code

/**
 * Created by baimao
 * Time:2020/3/11
 */

public class ResolveTest {

    public void methodA(){
        System.out.println("Hello MethodA");
        methodB();
    }

    public void methodB(){
        System.out.println("Hello MethodB");
    }

    public static void main(String[] args) {
        ResolveTest resolveTest = new ResolveTest();
        resolveTest.methodA();
    }


}

We decompile it with javap, and find methodA

public void methodA();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #3                  // String Hello MethodA
         5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: aload_0
         9: invokevirtual #5                  // Method methodB:()V
        12: return
      LineNumberTable:
        line 9: 0
        line 10: 8
        line 11: 12
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      13     0  this   LResolveTest;

As can be seen in the 0359 code lines we have used the symbolic references, # plus the number here is symbolic references, such as we saw in the ninth line, point # 5, go looking for the constant pool

 #1 = Methodref          #10.#27        // java/lang/Object."<init>":()V
   #2 = Fieldref           #28.#29        // java/lang/System.out:Ljava/io/PrintStream;
   #3 = String             #30            // Hello MethodA
   #4 = Methodref          #31.#32        // java/io/PrintStream.println:(Ljava/lang/String;)V
   #5 = Methodref          #7.#33         // ResolveTest.methodB:()V
   #6 = String             #34            // Hello MethodB
   #7 = Class              #35            // ResolveTest
   #8 = Methodref          #7.#27         // ResolveTest."<init>":()V
   #9 = Methodref          #7.#36         // ResolveTest.methodA:()V
  #10 = Class              #37            // java/lang/Object
  #11 = Utf8               <init>
  #12 = Utf8               ()V
  #13 = Utf8               Code
  #14 = Utf8               LineNumberTable
  #15 = Utf8               LocalVariableTable
  #16 = Utf8               this
  #17 = Utf8               LResolveTest;
  #18 = Utf8               methodA
  #19 = Utf8               methodB
  #20 = Utf8               main
  #21 = Utf8               ([Ljava/lang/String;)V
  #22 = Utf8               args
  #23 = Utf8               [Ljava/lang/String;
  #24 = Utf8               resolveTest
  #25 = Utf8               SourceFile
  #26 = Utf8               ResolveTest.java
  #27 = NameAndType        #11:#12        // "<init>":()V
  #28 = Class              #38            // java/lang/System
  #29 = NameAndType        #39:#40        // out:Ljava/io/PrintStream;
  #30 = Utf8               Hello MethodA
  #31 = Class              #41            // java/io/PrintStream
  #32 = NameAndType        #42:#43        // println:(Ljava/lang/String;)V
  #33 = NameAndType        #19:#12        // methodB:()V
  #34 = Utf8               Hello MethodB
  #35 = Utf8               ResolveTest
  #36 = NameAndType        #18:#12        // methodA:()V
  #37 = Utf8               java/lang/Object
  #38 = Utf8               java/lang/System
  #39 = Utf8               out
  #40 = Utf8               Ljava/io/PrintStream;
  #41 = Utf8               java/io/PrintStream
  #42 = Utf8               println
  #43 = Utf8               (Ljava/lang/String;)V

We call methodA in methodB method, by symbolic references, # 5 -> # 33 -> # 19

3, initialization

Static variable initialization phase will assign an initial value in the true sense. In front of the stage we are ready to assign an initial value is assigned a value of zero, and here we will truly value the initial assignment.
Such as: private static int num = 5;
in the preparation phase num = 0, but only in the initial stage num = 5.

4, class loader

Class loader There are four main kinds: the bootstrap class loader, the extension class loader, the system custom class loader and loader, usually we only use the first three default class loader.

Bootstrap class loader (Bootstrap Class Loader)
bootstrap class loader for loading JAVA core class, which is composed of C and C ++ written, as it relates to the local virtual machine, so the Bootstrap loader, we can not get to the .
** extension class loader (Extension Class Loader) **
extension class loader for loading in the extended class jre, realized by JAVA code, is indirectly derived ClassLoader class for all classes in the loading jre / lib / ext.
** system class loader (System Class Loader) **
say straightaway that is the system class loader is responsible for loading all of the class to write our own.

Let us look through the code three loader

public class ClassLoaderTest {

    public static void main(String[] args) {
        ClassLoader classLoader = ClassLoader.getSystemClassLoader();
        ClassLoader extClassLoader = classLoader.getParent();
        ClassLoader bootstrapClassLoader = extClassLoader.getParent();
        System.out.println(classLoader);
        System.out.println(extClassLoader);
        System.out.println(bootstrapClassLoader);
    }
}

Print results

sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$ExtClassLoader@1b6d3586
null

First we get through getSystemClassLoader () loader of the current class system class loader is then () Gets the top to the extension class loader through getParent, and then get the upper through getParent () bootstrap class loader, we just know that the bootstrap class loader can not be retrieved, so print out blank.

PS: a class loader first loads his parent

Parents delegate mechanism
parent appoint a mechanism appears to be the words difficult to understand, let's put a map

Parents delegate mechanism
When you need to load a class, he will be asked to reach the upper loader knows the bootstrap class loader, if upper loader and can not be loaded, then went on to load the subclass. FIG when to load a class, will be in the order of 1-> 2-> 3-> 4-> 5-> 6 to the load.

Meaning mechanism (advantage) parents delegate
their parents delegate mechanism appears to be too much trouble, but to protect the scheduling order to bootstrap class loader priority, can effectively prevent Java core libraries are modified, while preventing the kind of repeated loading. Let's take a look at the code.

package java.lang;

/**
 * Created by baimao
 * Time:2020/3/11
 */

public class String {
    public String() {
        System.out.println("this is String");
    }
}

We first create a package called java.lang, and in the package we have created a String such a class, we knew we were in the presence of such a class java.lang.String in Java within the database, then we re-create a class to call our String we may think in the end will not complain if the error can not see which class in the end will be loaded.

/**
 * Created by baimao
 * Time:2020/3/11
 */

public class ParentalTest {

    public static void main(String[] args) {
        java.lang.String s = new java.lang.String();
        System.out.println("success");
    }
}

To ensure that our class is loaded under the java.lang package, we found that print only "success"; here we can not help but see, write our own String class has not been loaded. This is the parents delegate mechanism, and some beginners on the dizzy, I do not see parents delegate of "Double" ah, here it is in fact a translation problem, not simply from the literal meaning to understand.

PS: And this protective mechanism is known as the sandbox security mechanism.

Fifth, the run-time data area (Runtime Data Area)

In fact, JVM run-time operation of the memory area data area. This part consists of 5 parts generally heap area, area method, PC register (also called the program counter) VM stack, native method stacks.

1, PC register (Program Counter Register)

The main role of the PC register is the address of the next instruction record. So register in the end what does that mean? Here registers its name from the register of the CPU, CPU load data into the register only to be able to run. However register here is not on the physical register it can be said to be an abstract CPU register it.

In our PC register, it is only used to store the address of the next instruction. PC register is also known as the line number indicator, on, for example, over the line of code, who performed the next line of code. By our execution engine to read the next instruction. Here it may be slightly more abstract understanding.
And other finished behind virtual machine stack may come back to understand relatively easy.

Let me talk about property register so few PC
1, PC register is a very small memory, running the fastest storage area, because it holds the address of the next instruction, so the memory is very small and fast.
2, the thread is private, its life cycle and thread synchronization
3, we know that any time a thread of execution, only one method is executed, this method is also called the current method, when the method of execution in the PC registers recorded address of the next instruction.
4, it does not exist OutOtMemory (memory overflow) and StackOverFlow (stack overflow), nor GC (garbage collection).

2, the virtual machine stack

The so-called virtual machine stack, it can be seen that the stack structure, after the advanced features, stack push pop operation it was only two operations. In talking about the virtual machine stack Let's look at the difference between the stack and the JVM heap among: Stack responsible for running Sung Hoon, while the heap to manage data storage.

So how virtual machine stack understanding, we look at the stack of virtual machine memory model

VM stack memory model
From this picture it is easy to see that our virtual machine thread stack is private, whenever a thread is created, a virtual machine stack began. Each virtual machine stack has a lot of stack frames (Stack Frame), and the stack frame is actually method. Stack stack frame is the current method. If you understand it more abstract, we can look at the code.

public class JVMStackTest {
    
    private void methodA(){
        methodB();
        System.out.println("Hello MethodA!");
    }
    
    private void methodB(){
        System.out.println("Hello MethodB!");
    }

    public static void main(String[] args) {
        JVMStackTest jvmStackTest = new JVMStackTest();
        jvmStackTest.methodA();
    }
}

Let's parse this code through a virtual machine stack, we call A first method, which stresses A method pushed onto the stack, then A method for the current method, A method then calls the method B, method B will soon pushed onto the stack, then B method post-stack, print "! Hello MethodB", return;, B popping method, A method becomes the current method is at the top, after printing "Hello MethodA!" pop.

When a general method is invoked, this method the stack frame on the stack when this method return, then the stack. As for the void, will return the byte code file. It is worth noting that the stack frame can not be shared, that can not be shared between threads and thread stack frames.

How JVM support multithreading
We know that multi-threaded operating mechanism, not all of the threads execute simultaneously, but you execute me a little bit and then you execute execute it. As two threads A, B, A thread executes two threads then the PC PC register register remember the address of the next instruction, but also for the implementation of thread B, B a few threads of execution and the cycle continues this process, but the entire schedule is by the JVM to perform.

VM stack StackOverFlowError
virtual machine stack stack structure since it is, then there must be a stack overflow, stack overflow simulate how we process it, take a look at the code

public class StackOverFlowTest {

    private static int count=0;
    public static void main(String[] args) {
        count++;
        System.out.println(count);
        main(args);
    }
}

Print results

11404
11405
11406
11407
11408
Exception in thread "main" java.lang.StackOverflowError

We found that when executed to 11408 level when it prompts stack overflow, and the Java Virtual Machine Specification, we can dynamically expanding virtual machine stack size can also be a fixed size, then how to set up a virtual machine stack size of it, by adding -Xss parameters to set the stack size.

2.1 stack frame

Described above probably describes the stack frame. Stack frame consists of five parts:
the local variable table, the operand stack, the return address of the method, dynamic link, the additional information.

2.1.1 local variable table

When it comes to the local variable table, you certainly have to understand what the local variables. Local variables, also called an internal variable, refers to the internal variables inside a function or a compound statement definition, parameters, and that is defined inside of a variable is called the method of local variables. The minimum unit of a local variable is a variable slot (SLOT).
Local variable table, storing eight basic types of data to compile understood, reference type and the return address type.
Local variable table, the type of occupancy within a 32-bit SLOT, 64-bit type uses two SLOT (Long and Double).
byte, short, char and boolean money in storage will become int type, occupying a SLOT.
Local variable table is present on the stack, and virtual machine thread stack is private, then it proves the local variable table also thread private data security is not an issue.
Local variable table need to determine its capacity at compile time, once determined can not be modified.
We can deepen understanding through the code.

public class LocalTest {

    private void methodA(String name){
        int a = 10;
        byte b = 1;
    }

    public static void main(String[] args) {
        LocalTest localTest = new LocalTest();
        localTest.methodA("aaa");
    }
}

We use javap -v to decompile bit to find the main method of LocalVariableTable

      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      15     0  args   [Ljava/lang/String;
            8       7     1 localTest   LLocalTest;

We can see the local variable table has two kinds of local variables, a parameter args there is a reference type localTest.

In the stack frame, the local variable table is the key to performance tuning. Variables local variable table is important for garbage collection root.

2.2 operand stack

Each individual has their own stack frame operand stack. Say they feel less able to understand, we look at the code.

public class OperantStackTest {

    public static void main(String[] args) {
        methodA();
    }

    public static void methodA(){
        int i = 1;
        int j = 2;
        int k = i + j;
    }

    public static void methodB(){
        int i1 = 0;
        i1 = i1++ + ++i1;
        System.out.println(i1);
    }


}

First we look methodA, by javap -v decompile it and find our methodA.

 public static void methodA();
    descriptor: ()V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=3, args_size=0
         0: iconst_1 //将常量1压入操作数栈
         1: istore_0 //取出操作数栈栈顶数据,放入局部变量表中索引为0的位置
         2: iconst_2 //将常量2压入操作数栈
         3: istore_1 //取出操作数栈栈顶数据,放入局部变量表中索引为1的位置
         4: iload_0 //将局部变量表中索引为0的数据数据压入操作数栈
         5: iload_1 //将局部变量表中索引为1的数据数据压入操作数栈
         6: iadd     //栈顶两数据相加,并压入操作数栈
         7: istore_2  //取出操作数栈栈顶数据,放入局部变量表中索引为2的位置
         8: return  //返回void
      LineNumberTable:
        line 13: 0
        line 14: 2
        line 15: 4
        line 16: 8
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            2       7     0     i   I
            4       5     1     j   I
            8       1     2     k   I

To deepen our understanding of the comments by progressive operand stack, if it is quite abstract, we will look at a map Operand stack
as shown we should be able to easily understand the role of the operand stack, interested students can take a look at our methodB print the value of the angle from bytecode to analyze the problem.
Stack caching technology
we can see by the above example, is in the operand stack in memory, too frequently bound to affect the efficiency of reading and writing data, so HOTSPOT proposed the stack caching, data caching in the top of the stack the physical CPU registers, improve the efficiency of our execution engine.

Released four original articles · won praise 2 · Views 3458

Guess you like

Origin blog.csdn.net/qq_40479674/article/details/104791384