Like attention, no more lost, your support means a lot to me!

🔥 Hi, I’m Chouchou. GitHub · Android-Notebook has been included in this article. Welcome to grow up with Chouchou Peng. (Contact information at GitHub)

preface

  • After the accumulation of the previous articles, you have mastered the structure of static Class files, as well as the dynamic process of virtual machine Class loading and bytecode execution.
  • This article, let’s talk about itJavaYou’ll see the entire process from source code to bytecode to native code. Please like it, your likes and attention really mean a lot to me!

directory


1. Classic program compilation principle

The process of translating source code into object code is called the compilation process. The classic program compilation process includes the following processes:

  • If the object code is understood as intermediate code, it is a compilation process in a narrow sense. For example, *.c files are compiled to generate *.obj files, or *.java files are compiled to generate *.class files.

  • If the object code is understood as the machine code that is ultimately executed, it is a compilation process in a broad sense. Obj files are linked to executable *.exe files, or *.class is interpreted/compiled to machine code;

In Java technology, unless there is a specific context, the term compile usually refers to the process by which *.Java is converted to *.class, also known as the compile front end. In addition, the term compilation can also refer to either just-in-time (JIT) compilation (Just in Time Compile) or (static) AOT (Ahead of Time Compile) compilation, which is called the Compile backend.

Here are a few tips for compiling the front end and the back end:


2. Compile the front end

The javac compiler is the most important compiler in the front-end stage of compilation. Executing javac command on the command line is essentially running javac.exe. Android engineers are probably familiar with the Gradle build process, which includes a Task: CompileDebugJavaWithJavac, actually also use the javac compiler, compiler intermediate path in the build/intermediates/javac/debug/classes.

2.1 javac compile

Below, we tidy up the main processes of the Javac compiler:

Extended article:

  • On the annotation processor, please read: the Java | annotation processor principle analysis and practice”
  • On the class loading, please read: the Java | talk about your understanding of the class loading process,
  • For method calls, please read: the Java | deep understanding of the essence of the method call (including overloading and rewrite the distinction)”

2.2 Java Common Syntax sugar

Syntactic sugar refers to a type of grammar in a high-level language that is converted to sugar-free grammar at compile time. Most of these syntactic sugars are implemented by the compiler, rather than by bytecode or virtual machine low-level support. The following table summarizes some of the familiar grammatical sugars:

Extended article:

  • On the generic, please read: “the Java | about generic can ask it’s all here (including Kotlin)”
  • On the inner class, please read: the Java | why a static inner class can hold outside class reference”
  • Regarding the switch, please read: the Java | switch and the if – else which is more efficient,

3. Compile the backend

In the compile back-end stage, the most important are the run-time just-in-time Compiler (JIT) and the static AOT (Ahead of Time Compiler).

3.1 Explain execution & Compile execution

From the previous section, we know that the core build artifact of the build front end is the Class file. But as far as the CPU is concerned, it doesn’t recognize bytecode. In the Java | why Java implementation platform neutrality “in this article, we emphasize the: each CPU can” read “their support of machine language or native code (native code).

Therefore, when Java VIRTUAL machines execute bytecodes, the bytecodes need to be translated into the local code of the current platform, which can be divided into: interpret execution & compile execution, as follows:

It is important to note that not all Java virtual machines have an interpreter and compiler operating architecture. When just-in-time compilation is triggered, the execution engine (by default) does not wait for just-in-time compilation to complete, but resumes execution as explained. The method entry address is not changed until immediate compilation is complete.

3.2 Just-in-time compiler hotspot detection

So how does the just-in-time compiler detect hot code? Specifically, there are two types of hot code to detect: methods that are called multiple times & bodies of loops that are executed multiple times. The detection methods used are: Sample-based & counter based:

3.3 Compiler optimization techniques

Editting…


4. To summarize

  • The main purpose of the optimization measures of compiler front-end is to reduce programmer’s coding complexity and improve coding efficiency. Syntactic sugar is not dependent on bytecode or the underlying support of the virtual machine and is converted to the underlying sugar-free syntax after compilation. In addition, the annotation processor acts as a plug-in for the compiler through which developers can influence front-end compilation.

  • The main purpose of the compiler backend optimization measures is to generate more efficient machine code and improve the running efficiency. Precompile Compile bytecode before the program is run. The just-in-time compiler dynamically monitors the program at run time, detects hot code and compiles it into native code, which is more efficient but requires a warm-up period.


The resources

  • In Depth understanding the Java Virtual Machine (version 3) (chapters 10 and 11). By Zhou Zhiming
  • Understanding Android in Depth: Java Virtual Machine ART by Deng Fanping
  • Understanding JVM Bytecode in Depth (chapters 4 and 5). By Ya Zhang

Creation is not easy, your “three lian” is chouchou’s biggest motivation, we will see you next time!