A picture to understand the JVM

     Every Java developer knows that bytecode is executed through JRE (Java Runtime Environment), JRE implements JVM, and JVM can parse and execute bytecode files.

     What is JVM?

     A virtual machine is a piece of software that is an implementation of a physical machine. Java development is built on the idea of ​​Write Once Run Anywhere . The Java compiler first compiles the Java code into a .class file. The Class file is loaded into the JVM for parsing and execution.

JVM architecture diagram:

JVM Architecture Diagram

 

How does the JVM work (this article focuses on mainstream HotSpot virtual machines)? As shown in the figure above, the JVM is mainly divided into three main systems:

  • class loading system
  • runtime data area
  • execution engine

1. Class Loader System

     The class loader loads the data describing the class from the class file into the memory, and verifies, converts, parses and initializes the data, and finally forms a Java type that can be directly used by the virtual machine. Unlike languages ​​that require linking at compile time, class loading in Java is done at runtime. The following is the main process of class loading:

1.1 Loading, there are mainly three types of class loaders:

        Bootstrap ClassLoader: Bootstrap ClassLoader, same as above. It is responsible for loading the class library stored in JDK\jre\lib (JDK represents the installation directory of JDK, the same below), or in the path specified by the -Xbootclasspath parameter, and can be recognized by the virtual machine (such as rt.jar, all The classes starting with java.* are loaded by Bootstrap ClassLoader). The startup class loader cannot be directly referenced by a Java program.

        Extension class loader: Extension ClassLoader, which is implemented by sun.misc.Launcher$ExtClassLoader, which is responsible for loading all classes in the JDK\jre\lib\ext directory or the path specified by the java.ext.dirs system variable Libraries (such as classes starting with javax.*), developers can directly use the extension class loader.

        Application class loader: Application ClassLoader, this class loader is implemented by sun.misc.Launcher$AppClassLoader, which is responsible for loading the classes specified by the user class path (ClassPath), developers can use this class loader directly, if the application The program has not customized its own class loader. In general, this is the default class loader in the program.

When loading class files, the above class loader will follow the parent delegation model. If a class loader receives a class loading request, it will not load it first, but delegate the request to the parent class loader to execute , if the parent class loader still has its parent class loader, it will further delegate upwards, recursively in turn, and the request will eventually reach the top-level startup class loader. If the parent class loader can complete the class loading task, it will return successfully. If the parent class loader can complete the class loading task, it will return successfully. The class loader cannot complete this loading task, and the sub-loader will try to load it by itself. See the loadClass method of classLoader to load a class

 protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // First, check if the class has already been loaded
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                    if (parent != null) {
                        // 首先委托给父类去加载
                        c = parent.loadClass(name, false);
                    } else {
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }

                if (c == null) {
                    // z自行加载
                    long t1 = System.nanoTime();
                    c = findClass(name);

                    // this is the defining class loader; record the stats
                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    sun.misc.PerfCounter.getFindClasses().increment();
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }

1.2 Connection

     Verification - The purpose of verification is to ensure that the information contained in the byte stream in the Class file meets the requirements of the current virtual machine, and does not compromise the security of the virtual machine itself.

     Prepare - The prepare phase is the stage where memory is formally allocated for class variables and initial values ​​for class variables are set, all of which will be allocated in the method area. The initial value set here is usually the default zero value of the data type (such as 0, 0L, null, false, etc.), rather than the value that is explicitly assigned in the Java code.

     Parsing - The parsing phase is the process by which the virtual machine converts the symbolic references in the constant pool into direct references;

1.3 Initialization

     Initialization is the last step in the class loading process. At this stage, the Java program code defined in the class is actually executed. In the preparation stage, the class variable has been assigned the initial value required by the system, and in the initialization stage, the class variable and other resources are initialized according to the subjective plan specified by the programmer through the program.

2. The runtime data area, the runtime data area is mainly divided into the following 5 areas:

  1. Method Area – The method area is a memory area shared by each thread, which is used to store data such as class information, constants, static variables, and code compiled by the compiler that have been loaded by the virtual machine.
  2. Heap (Heap Area) - Heap is also a memory area shared by each thread, not thread-safe. Created when the virtual machine starts, mainly used to store object instances.
  3. Stack Area - The virtual machine stack is private to the thread, and its life cycle is the same as that of the thread. When each method is executed, the virtual machine will create a stack frame to store information such as local variable table, operand stack, dynamic link and method exit.
  4. Program Counter Registers - Line number indicator of the bytecode line number executed by the current thread, private to each thread. The multithreading of the Java virtual machine is achieved by switching threads in turn and distributing the execution time of the processors. At any given moment, a processor will only execute instructions in one thread. In order to restore the correct execution position after thread switching, each thread needs a thread counter to record the address of the virtual machine bytecode instruction.
  5. Native Method stacks – The native method area is similar to the stack, except that the native method area executes virtual machine Native methods.

3. Execution engine

After the bytecode is loaded into the Runtime Data Area, it will be executed by the execution engine. The execution engine is mainly divided into the following components:

  • Interpreter - The parser is fast in parsing bytecode, but slow in execution. Its disadvantage is that when a method is called multiple times, a new parser needs to be created each time.
  • JIT Compiler – When encountering the same code, the JIT compiler treats the same bytecode as a native method.
  • Garbage Collector

 

 

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325382329&siteId=291194637