Interviewer: Starting with the basics, how do you understand that Java is a “cross-platform” language, meaning “compiled once, run everywhere”?

Candidate: It makes sense because we have JVMS.

Candidate: Java source code is compiled into class files, which run on the JVM.

Candidate: When we install JDK in daily development, we can find that JDK is “different operating system”, JDK includes JVM, so Java relies on JVM to achieve “cross-platform”.

Candidate: The JVM is operating system-oriented and is responsible for interpreting Class bytecode into instructions that the system can recognize and execute, as well as managing memory while the program is running.

Interviewer: Why don’t you talk about the process from the source file (.java) to the code execution?

Candidate: Well, no problem

Candidate: To summarize, I think there are 4 steps: compile -> load -> explain -> execute

Candidate: Compile: Compile the source file into a class file that the JVM can interpret.

Candidates: The compilation process does “parsing”, “semantic”, “annotation”, and so on on the source code program before generating the bytecode file.

Candidates: Things like erasure of generics and Lombok, which we use a lot, are done at compile time.

Candidate: Load: Loads the compiled class file into the JVM.

Candidate: Several more steps can be refined during the load phase: load -> connect -> initialize

Candidate: Let me elaborate on these steps.

Candidate: [Load timing] To save memory, not all classes are loaded into the JVM at once, but only when “needed” (new, reflection, etc.)

Candidate: The class file is loaded into the JVM by a “class loader”. To prevent multiple copies of the same bytecode from being in memory, the parent delegate mechanism is used (it does not try to load the class itself, but delegates requests to the parent loader, up).

Candidate: The Bootstrp loader is used to load the local method classes in JDK, and the ExtClassLoader is used to load the internal extension classes in JDK. The class files in the program are loaded by the system loader (AppClassLoader).

Candidate: What it does in this load phase can be summarized as: find and load the binary data of the Class, create an object of the Java.lang. Class Class in the JVM “heap”, and store the class-related information in the JVM “method area”

Interviewer: HMM…

Candidate: After the “load” step, the class file is now loaded into the JVM, the corresponding class object is created and the class information is stored in the method area.

Candidate: The “connect” phase can be summarized as: it validates the class information, allocates memory space for “class variables” and assigns default values to them.

Candidate: The join can be further refined into several steps: validate -> prepare -> parse

Candidates: 1. Validation: Verifies that the class complies with the Java specification and JVM specification

Candidates: 2. Preparation: Allocates memory for static variables of the class, initialized to the initial value of the system

Candidates: 3. Parsing: The process of turning symbolic references into direct references

Interviewer: HMM…

Candidate: After going through the connect step, class information is now validated and memory space and default values are allocated.

Candidate: Next comes the “initialization” phase, which can be summarized as assigning the correct initial values to static variables of the class.

Candidate: The process is roughly a collection of class static variables, static code blocks, static methods, and () methods, and then executes from the top down.

Candidate: If instantiated object calls a method to initialize the instance variable and execute the code in the corresponding constructor.

Candidate: With all this talk, it’s really only the loading phase (compile -> load -> explain -> execute), so what does the explain phase do

Candidate: After initialization, when we try to execute a method of a class, we find the bytecode information for the method, which is then interpreted by the interpreter into instructions that the system recognizes.

Candidate: What it does in this “interpret” phase can be summed up as translating bytecode into instructions that the operating system recognizes

Candidates: There are two ways to interpret bytecode information into machine instructions during the interpretation phase, a bytecode interpreter and a just-in-time compiler (JIT).

Candidate: The JVM compiles the “hot code” and interprets the off-hot code directly. When the JVM finds that a method or block of code is being run particularly frequently, it is possible to identify that piece of code as “hot code”

Candidate: Use hotspot detection to detect if it is hotspot code. “Hot spot detection” generally has two ways, counters and sampling. HotSpot uses a “counter” approach to detection, with two types of counters for each method: method call counters and backside counters

Candidate: Both counters have a certain threshold, and when the counter overflows, JIT compilation is triggered.

Candidate: The just-in-time compiler stores the instructions for a hot method and executes the cached machine language the next time it executes without having to repeat the interpretation

Interviewer: HMM…

Candidate: After the explanation phase, it’s finally the implementation phase.

Candidate: The “execute” phase can be summed up as: the operating system parses the instructions from the interpreter and calls the system’s hardware to execute the final program instructions.

Candidates: This is my understanding of the process from source files (.java) to code execution.

Interviewer: HMM… I also want to ask you about the parental delegation model you mentioned earlier…

Candidate: Next time!

This paper concludes:

  • Java is cross-platform because the UNDERLYING operating system is shielded by the JVM

  • Java source code to the process of execution, from the PERSPECTIVE of the JVM can be summarized into four steps: compile -> load -> interpret -> execute “compile” through syntax analysis, semantic analysis, annotation processing finally generated class file “load” can be subdivided into steps: load -> connect -> initialize. Load loads the class file into the JVM, connect verifies class information, allocates memory, and assigns default values, and initialize assigns variables to correct initial values. Interpreting translates bytecode into execution instructions that the operating system can recognize. There are bytecode interpreters and just-in-time compilers in the JVM. In the interpretation of the code will be analyzed to see whether it is “hot code”, if it is “hot code” will trigger JIT compilation, the next execution will not need to repeat the interpretation, improve the speed of interpretation “execution” call system hardware to execute the final program instructions