Tencent, Alibaba, JD.com tells you why Java needs to balance method calls and inlining

This article mainly introduces why Java needs to balance method invocation and inlining to help you better understand and use Java. Interested friends can understand that
in Java, method invocation is generally through Virtual Call and Classic Call.

Classic Call refers to the address of the method directly. It needs to be addressed to the address of the method once, which is slower than executing the code directly.

Virtual Call requires VMT (Virtual Method Table). This VMT stores all the Virtual Methods in the class object. When the program runs, it first loads the instance object, then finds the VMT through the instance object, and then finds the corresponding method address through the VMT, and then executes the code. So it is slower than Classic Call.

In Java, except for static methods, private methods, and constructors that are Classic Calls, they are basically Virtual Calls.

In order to optimize, when the JVM is running, the JVM uses a mixed mode to convert the bytecode into the machine code that the machine can run. The mixed mode includes an interpreter and JIT:

when compiling, it mainly compiles java source code files into java unified words Save the code, but the compiled bytecode cannot be run directly, but read and run through the JVM. The interpreter in JVM translates the .class file line by line and then runs it. Translation is converted into machine code that can be run on the current machine. It does not translate the entire file at once, but translates one sentence, executes one sentence, and then Translate and execute it again, so the interpreter's program will run slowly, and it will be executed after interpretation each time. So, sometimes, we wonder whether we can cache the content after the explanation, so that it can not be run directly? However, if every piece of code has to be cached, for example, the code that is executed only once is also cached, which is a waste of memory. Therefore, a new runtime compiler, JIT, is introduced to solve these problems and accelerate the execution of hot codes.

**JIT runtime compiler working mechanism: **

JIT compiles and deeply optimizes hot code. The optimized machine code will be cached and stored in CodeCache (code cache). For non-hot code, such as code that only runs once (class constructor, etc.), direct interpretation and execution is faster. JIT not only spends more time to compile and optimize, but also consumes a lot of memory. The bytecode is converted into executable machine code, and the size will be many, many times larger. This is why the interpreter has to translate and execute every time, and the JIT only compiles and optimizes the hot code. Some common optimization operations performed by the JIT compiler include data analysis, conversion from stack operations to register operations, reduction of memory access through register allocation, and elimination of common sub-expressions. The higher the degree of optimization performed by the JIT compiler, the more time it takes in the execution phase. Therefore, the JIT compiler cannot afford all the optimizations done by the static compiler, not only because it increases the execution time overhead, but also because it only limits the program. This also explains why some JVMs choose not to always do JIT compilation, but choose to use a hybrid execution engine of interpreter + JIT compiler.

One of the most important optimizations of JIT is inlining: inlining is the process of merging or "inlining" the tree of smaller methods into the tree of its caller. This can speed up frequently executed method calls. Different algorithms are used in different hierarchical optimization stages. mainly includes:

  • Trivial method inlining
  • Call graph inline
  • Tail recursive elimination
  • Virtual call optimization
    thus omits the calling method. However, if all methods are inlined, the compiled machine code will be very large, the memory usage will increase sharply, and the efficiency will be low. Therefore, JIT needs to grasp the degree of optimization

To sum up: JIT optimizes and compiles code on the fly. The optimized code includes inlining. The compiled code is stored in memory, which is the code cache. The compiled code is very large, so it is not possible to compile all the code. Is the hot code. And, inlining will also make this method bigger. The code cache also needs to be cleaned. If the code cache occupies too high, it will also increase the probability of cleaning, because you may execute several methods with high frequency, but after compilation, the occupancy is too large and the code cache limit is exceeded. Cache cleaning means that the compiled code in the code cache is constantly changing. Clearing the code cache will allow all threads to enter Safepoint before being cleaned up, that is, stop the world. Too much inline, the method becomes larger, and the frequency of this cleaning becomes larger.

The above is the detailed content of why Java needs to balance method invocation and inlining. For more information about Java balanced method invocation and inlining, please pay attention to other related articles in the editor!

Guess you like

Origin blog.csdn.net/dcj19980805/article/details/115310435