Preface:
As you all know, the importance of the JVM in Java, learning the JVM will give you a good understanding of how Java works, the compilation process and how to tune Java programs. The JVM is also a very important part of the interview, such as JVM tuning, JVM object allocation rules, memory model, method area, and GC.
Without further ado, let’s take a look at the JVM.
What is the JVM?
The JVM(Java Virtual Machine) is an abstract computer that, like a real computer, has an instruction set and uses different storage areas. It is responsible for executing instructions and managing data, memory, and registers.
For those of you who don’t understand the JVM, this is confusing. That’s ok. Let me walk you through the architecture diagram of the JVM in detail, and maybe you’ll get some idea.
Simply put, the JVM is a virtual computer. We all know that one of the features of the Java language is cross-platform, and the JVM is a key part of implementing cross-platform Java programs. When a Java compiler compiles a Java program, it generates platform-independent bytecodes (.class files). Platform-independent bytecodes are executable on Windows, Linux, and Mac operating systems. That is, the.class files generated by Java compilation are not platform-oriented, but jVM-oriented. JVMS on different platforms are different, but they all provide the same interface. Figure 1 shows the general running steps of Java:
Here’s an example from the Crazy Java Handout to help you understand what the JVM can do:
The JVM works like having two different pencils, but you need to put the same pen cap on two different pens. You only need to provide a converter for each pen, which has the same upward interface to fit the same pen cap. The downward interface is different to accommodate two different pens. In this analogy, it is roughly understood that two different pens are different operating systems, the same pen cap is a Java bytecode program, and the converter role corresponds to the JVM. Similarly, the JVM can be thought of as being split up and down, with JVMS on all platforms providing exactly the same interface to Java bytecode programs up, but adapting to different platforms down.
Overview of THE JVM architecture
We have given you an overview of what the JVM can do, but to understand it in depth we need to understand the architecture of the JVM, as shown in Figure 2:Figure 2 shows the ARCHITECTURE of the JVM, so let’s talk about what each part means.
1. ClassLoader subsystem (ClassLoader)
The class file is labeled at the beginning of the file, loads the bytecode content of the class file into memory, converts that content into a runtime data structure in the method area, and the ClassLoader is only responsible for loading the class file. Whether it can run or not, It’s up to the Execution Engine.
The *.class file generated by Java compilation is loaded by the ClassLoader, so there are several problems:
How does the ClassLoader know that the *. Class file is the one to load? If I manually change the extension name of a normal file to the class suffix, will the ClassLoader load the file? In fact, the class file is marked with a specific file identifier at the beginning of the file. Write any Java program, compile and generate a class file, and open it with something like this:Cafe Babe is a class file identifier. The ClassLoader is responsible for loading the class file containing cafe Babe. It loads the bytecode contents of the class file into memory. The ClassLoader is only responsible for loading the class file. It is up to the Execution Engine to execute it. See Figure 3.The Car. Class file is loaded into memory by the ClassLoader. The Car class is a template that can be instantiated into car1, car2, and car3.
What kind of loader is used to load Car. Class in Java? To answer this question, let’s write a simple code:
// New a Car object
Car car = new Car();
/ / this
ClassLoader classLoader = car.getClass().getClassLoader();
// Print the result
System.out.println(classLoader);
Copy the code
The result is: Let’s look at another set of code:
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: " Courier New" ! important; font-size: 12px ! important;"> // New two different objects
Car car = new Car();
String string = new String(); / / this
ClassLoader classLoader1 = car.getClass().getClassLoader();
ClassLoader classLoader2 = string.getClass().getClassLoader(); // Print the resultSystem.out.println(classLoader1); System.out.println(classLoader2); </pre>Copy the code
The result is:Sun.misc.Launcher$AppClassLoader@18b4aac2: null ClassLoader: null The car object is a class written by us, and the String object is a class of the system. Simply put, the ClassLoader selects different classloaders for different classes. This is where ClassLoader classification comes in
ClassLoader class:
Start the class loader (BootStrap) Extension class loader (Extension) application class loader (AppClassLoader) user-defined loader Is usually written by our own class with class loaders are AppClassLoader, It is “sun.misc.Launcher$AppClassLoader@18b4aac2” as shown above. Why is string null? In fact, this “null” refers to using the BootStrap loader.
AppClassLoader (car) : AppClassLoader (car) : AppClassLoader (car) : AppClassLoader (car) : AppClassLoader (car) Where can I use the BootStrap loader? The BootStrap loader is the ancestor of the extension class loader and the application class loader. If BootStrap is used, it is null because the upper level of the BootStrap does not exist
We can find the location of the String class in the JDK:
$JAVA_HOME/jre/lib/rt.jar/java/lang
Copy the code
All classes in the $JAVA_HOME/jre/lib/rt.jar jar package are loaded using BootStrap.
See Figure 4 below:Here you can see it very clearly:
1. All files in $Java_Home/jre/lib/rt.jar are loaded by BootStrap
$Java_Home/jre/lib/ext/*.jar is loaded with Extension
3. All classes in $CLASSPATH are loaded by SYSTEM (the application class loader is also called the SYSTEM class loader, which loads all classes in the current application CLASSPATH)
Let’s look at another example:
What if you created a java.lang package, then created the String class, and printed a sentence to execute it?
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: " Courier New" ! important; font-size: 12px ! important;">package java.lang; public class String { public static void main(String[] args) {
System.out.println("Hello World");
}
}</pre>
Copy the code
The effect is as follows:The main method is not found, but there is a main method why did not execute? This is where the parent delegate mechanism comes in
Parent delegate mechanism:
When a class receives a classload request, it first does not attempt to load the class itself. Instead, it delegates the request to its parent class. This is true of every hierarchical classloader, so all load requests should be passed to the starting classloader. The subclass loader will try to load the request itself only if the parent Class loader reports that it is unable to complete the request (the desired Class is not found in its load path).
So here’s how it actually works:
The ClassLoader received a loading request for the String class. If the class does not exist, the request cannot be completed. However, it happens that the java.lang.Stirng class is found in rt.jar and executes the class. He will find the java.lang.String class in the JDK, which does not define a main method. In short, it executes the java.lang.String class in the JDK, not our own class.
So what are the benefits of parental delegation:
One advantage of using parental delegation is that, for example, loading the java.lang.Object class in the rt.jar package, whichever loader loads the class ends up delegating to the top bootstrap class loader, thus ensuring that different classloaders will end up with the same Object.
2. Execution Engine
The execution engine is responsible for interpreting commands and submitting them to the operating system for execution. The execution engine is not explained too much here, as long as it is responsible for interpreting commands.
3. Native Method Stack and Native Method Interface
Local interface: the role of the local interface is the fusion of different programming languages for Java, its original purpose is the fusion of C/C++ programs, Java was born when C/C++ rampant, to have a foothold, must call C/C++ programs, Therefore, a special area of memory is created to process the code marked as Native by registering native methods in the Stack and loading native Libraies during Execution of the Execution Engine. This approach is being used less and less today, except in hardware-related applications, such as driving printers through Java programs or managing production equipment through Java systems, which are rare in enterprise applications. Because the communication between heterogeneous domains is very developed, for example, Socket communication can be used, Web Service can also be used, and so on, I will not introduce.
If you see the native keyword in your application, it means that you need to load the native method library to do something that Java can’t do
Native Method Stack: This is implemented by registering Native methods in the Stack and loading the local Method library at Execution Engine time. In plain English, local methods are registered by the local method stack, and methods in Java are registered by the Java stack.
4.PC Register (Program Counter Register)
Each thread has a program counter, thread is private, is a pointer that points to the method area of bytecode (used to store to the address of the next instruction, also the instructions to be executed code), by reading the next instruction execution engine, is a very small memory space, almost can ignore don’t remember. This small area of memory is a line number indicator of the bytecode being executed by the current thread, and the bytecode interpreter changes the value of this counter to select the next bytecode instruction to be executed. If a Native method is executed, the counter is empty. PC register is used to complete branch, loop, jump, exception handling, thread recovery and other basic functions. Because the memory used is small, no OutOfMemory errors occur.
The last
In addition, I have collated and collected more than 20 years of interview knowledge points, and a variety of Java core knowledge points to share with you for free, if you want information, please scan yourself to receive, code nuggets.
So that’s where this article ends, and we’ll continue talking about method areas, stacks, and heaps………. in the next article