JVM-execution engine

Execution engine overview

Execution engine location

The execution engine belongs to the lower layer of the JVM, which includes: interpreter, just-in-time compiler, garbage collector

Insert picture description here

What is the execution engine

  • The execution engine is one of the core components of the Java virtual machine. "Virtual machine" is a concept relative to "physical machine". Both machines have code execution capabilities. The difference is that the execution engine of the physical machine is directly built on the processor, cache, instruction set and operating system levels. , And the execution engine of the virtual machine is realized by the software itself, so the instruction set and the structure of the execution engine can be customized without being restricted by physical conditions, and it can execute those instruction set formats that are not directly supported by the hardware.

  • The main task of JVM is to load bytecode into it, but bytecode cannot run directly on the operating system, because bytecode instructions are not equivalent to local machine instructions. It contains only some Bytecode instructions, symbol tables, and other auxiliary information recognized by the JVM.

  • So, if you want to make a Java program run, the task of the Execution Engine isInterpret/compile bytecode instructions into native machine instructions on the corresponding platformThat's all right. Simply put, the execution engine in the JVM acts as a translator who translates high-level languages ​​into machine languages
    Insert picture description here.
    It translates the bytecode file into the machine language that the operating system knows.

Execution engine work process

  • What bytecode instructions the execution engine needs to execute during the execution process completely depends on the PC register.
  • Every time an instruction is executed, the PC register will update the address of the next instruction that needs to be executed.
  • Of course, during the execution of the method, the execution engine may accurately locate the object instance information stored in the Java heap area through the object reference stored in the local variable table, and locate the target object through the metadata pointer in the object header Type information.
  • From the appearance point of view, the execution engine input, processing, and output of all Java virtual machines are the same: the input is a bytecode binary stream, and the processing process is an equivalent process of bytecode analysis, execution, and instant compilation, and the output Is the execution process
    Insert picture description here

Java code compilation and execution process

Interpreted execution and just-in-time compilation

Before most of the program code is converted into the target code of the physical machine or the instruction set that the virtual machine can execute, it needs to go through the various steps in the following figure:

  • The orange part in front is the process of compiling and generating bytecode files (javac instructions), which has nothing to do with JVM

  • The following green (interpretation execution) and blue (just-in-time compilation) are the processes that JVM needs to consider
    Insert picture description here

  • Java code compilation is done by the Java source code compiler, the flowchart is shown below
    Insert picture description here

  • The execution of Java bytecode is completed by the JVM execution engine. The flowchart is shown below
    Insert picture description here* We use a general diagram to summarize the interpreter and the compiler
    Insert picture description here

Interpreter and compiler

  • What is an interpreter? What is a JIT compiler?
    • Interpreter: When the Java virtual machine is started, the bytecode will be interpreted line by line according to the predefined specifications, and the content of each bytecode file will be "translated" into the local machine instructions of the corresponding platform carried out. In layman's terms: java bytecode -> c++ code -> machine language
    • JIT (Just In Time Compiler) compiler: It is the virtual machine that directly compiles java bytecode into the machine language related to the local machine platform.
  • Interpreter classification
    • In the development history of Java, there are two sets of interpretation executors, namely the ancient bytecode interpreter and the template interpreter commonly used now.

      • The bytecode interpreter simulates the execution of bytecode through pure software code during execution, which is very inefficient.
      • The template interpreter associates each bytecode with a template function, and the template function directly generates the machine code when the bytecode is executed, which greatly improves the performance of the interpreter
    • In HotSpot VM, the interpreter is mainly composed of Interpreter module and Code module.

      • Interpreter module: implements the core functions of the interpreter
      • Code module: used to manage the local machine instructions generated by the HotSpot VM at runtime
  • The current state of the interpreter
    • Because the interpreter is very simple in design and implementation, in addition to the Java language, there are many high-level languages ​​that are also executed based on the interpreter, such as Python, Perl, Ruby, etc. But today, interpreter-based execution has become synonymous with inefficiency and is often ridiculed by some C/C++ programmers.

    • To solve this problem, the JVM platform supports a technology called just-in-time compilation. The purpose of just-in-time compilation is to prevent the function from being interpreted and executed, but to compile the entire function body into machine code. Each time the function is executed, only the compiled machine code is executed. This method can greatly improve the execution efficiency.

    • However, the interpreter-based execution mode still makes an indelible contribution to the development of intermediate language.

JIT compiler

  • The "compilation period" of the Java language is actually a period of "uncertain" operation

    1. Because it may refer to the process by which a front-end compiler (actually called "compiler front-end" is more accurate) converts .java files into .class files
    2. It may also refer to the process by which the back-end runtime compiler (JIT compiler, Just In Time Compiler) of the virtual machine converts bytecode into machine code.
    3. It may also refer to the process of directly compiling the .java file into local machine code using a static ahead of time compiler (Ahead of Time Compiler).
  • Typical compiler:

    • Front-end compiler: Sun's javac, incremental compiler (ECJ) in Eclipse JDT.
    • JIT compiler: C1 and C2 compiler of HotSpot VM.
    • AOT compiler: GNU Compiler for the Java (GCJ), Excelsior JET.

in conclusion

  • Although the execution performance of the program in the JRockit VM will be very efficient, the program will inevitably take longer to compile at startup. For server-side applications, startup time is not the focus of attention, but for those application scenarios that value startup time, it may be necessary to adopt an architecture where an interpreter and a just-in-time compiler coexist in exchange for a balance.
  • When the interpreter and the just-in-time compiler coexist, when the Java virtualizer is started, the interpreter can play a role first, instead of waiting for the just-in-time compiler to be completely compiled before execution, which can save a lot of unnecessary compilation time. As time goes by, the compiler comes into play, compiling more and more codes into local codes, and gaining higher execution efficiency .
  • At the same time, interpretation and execution serve as the compiler's "escape door" when the compiler's radical optimization fails.

Compilation object and trigger condition

The target that will be compiled on the fly during operation is the "hot code", the so-called hot code here includes:

  • Methods that are called multiple times
  • Loop body executed multiple times
    In both cases, the target of compilation is the entire method body.

Hot spot detection technology

  • The hot spot detection method currently used by HotSpot VM is counter-based hot spot detection.

  • Using counter-based hot spot detection, HotSpot VM will create two different types of counters for each method, namely the method invocation counter (Invocation Counter) and the back edge counter (Back Edge Counter).

    • Method call counter is used to count the number of method calls
    • The edge return counter is used to count the number of loops executed by the loop body

Method call counter

  1. This counter is used to count the number of times the method is called. Its default threshold is 1500 times in Client mode and 10000 times in Server mode. If this threshold is exceeded, JIT compilation will be triggered.

  2. This threshold can be set manually through the virtual machine parameter -XX:CompileThreshold.

  3. When a method is called, it will first check whether the method has a JIT-compiled version

    • If it exists, the compiled native code will be used first to execute
    • If there is no compiled version, add 1 to the call counter value of this method, and then determine whether the sum of the method call counter and the return counter value exceeds the method call counter threshold.
      • If the threshold is exceeded, a code compilation request for this method will be submitted to the just-in-time compiler.
      • If the threshold is not exceeded, use the interpreter to interpret and execute the bytecode file
        Insert picture description here

Heat decay

  • If nothing is set, the method call counter does not count the absolute number of method calls, but a relative execution frequency, that is, the number of method calls within a period of time.
  • When a certain time limit is exceeded, if the number of method calls is still not enough for it to be submitted to the just-in-time compiler for compilation, then the method call counter will be reduced by half. This process is called the counter decay of the method call counter. , And this period of time is called the Counter Half Life Time (Counter Half Life Time)
  • The half-life cycle is a concept in chemistry. For example, the age of unearthed cultural relics can be obtained by checking C60.
  • The JVM's heat decay is performed by the way when the virtual machine is garbage collected. You can use the virtual machine parameter -XX:-UseCounterDecay to turn off the heat decay
  • If you let the method counter count the absolute number of method calls, as long as the system runs for long enough, most methods will be compiled into local code.
  • In addition, you can use the -XX:CounterHalfLifeTime parameter to set the time of the half-life cycle, in seconds

Backward counter

  • Its function is to count the number of executions of the loop body code in a method, and the instruction that encounters the control flow backward jump in the bytecode is called "Back Edge".
  • Obviously, the purpose of establishing back-side counter statistics is to trigger on-stack replacement (OSR) compilation.Insert picture description here
  • Note: Although the compilation action is triggered by the loop body, the hot spot is only a part, but the compiler must use the entire method as the compilation object, but the execution entry will be different, and the bytecode serial number will be passed in during compilation.

C1 C2 compiler comparison

  • There are different optimization strategies on different compilers. On the C1 compiler, there are mainly methods for inlining, de-virtualization, and surplus elimination.
  • Method inlining: Compile the referenced function code to the reference point, which can reduce the generation of stack frames, reduce parameter passing and jump processes
  • De-virtualization: inline the only implementation fan
  • Redundancy elimination: fold out some code that will not be executed during operation
  • The optimization of C2 is mainly at the global level, and escape analysis is the basis of optimization. There are several optimizations on C2 based on escape analysis:
  • Scalar replacement: replace the attribute value of the aggregate object with a scalar value
  • Allocation on the stack: allocate objects on the stack instead of the heap for objects that have not escaped
  • Synchronization elimination: Clear synchronization operation, usually referred to as synchronized

Layered compilation strategy

  • Tiered Compilation (Tiered Compilation) strategy: Program interpretation and execution (without performance monitoring enabled) can trigger C1 compilation and compile bytecode into machine code. Simple optimization can be performed, or performance monitoring can be added. C2 compilation will be based on performance monitoring Radical optimization of information.

  • However, after the Java7 version, once the developer explicitly specifies the command "-server" in the program, the hierarchical compilation strategy will be turned on by default, and the C1 compiler and C2 compiler will cooperate with each other to perform compilation tasks.

to sum up

  • Generally speaking, the performance of the machine code compiled by JIT is higher than that of the interpreter.
  • The startup time of C2 compiler is slower than C1. After the system is executed stably, the execution speed of C2 compiler is much faster than C1 compiler.

Graal compiler

  • Since JDK10, HotSpot has added a new just-in-time compiler: Graal compiler
  • The compilation effect has been equal to the G2 compiler in just a few years, and the future can be expected
  • At present, with the experimental status label, you need to use the switch parameter to activate
    -XX:+UnlockExperimentalvMOptions -XX:+UseJVMCICompiler

Guess you like

Origin blog.csdn.net/null_zhouximin/article/details/112853573