First, take a look at a simple overview of how the JVM works as a whole

Simply put, the “.java” code files are first compiled into “.class” bytecode files, and the class loader loads the classes from the “.class” bytecode files into the JVM, which then executes the code for those classes.

Class loading process

When the class is loaded for use, it goes through the following process

Load -> Verify -> Prepare -> Parse -> Initialize -> Use -> Uninstall

(1) Under what circumstances does the JVM load a class?

When you use this class in your code. For example, there is a class (DemoMain. Class) that has a main method as the main entry

Once the JVM starts, the class is loaded into memory and executed from the entry code of the main method.

The Demo object is then instantiated in the code, at which point the class of the “demo.class” bytecode file needs to be loaded into memory.

public class DemoMain { public static void main(String[] args) { Demo demo = new Demo(); }}Copy the code

Summary: First, the main class in your code that contains the main method must be loaded into memory after the JVM process starts to execute the code in the main method

When another class is used, the class is loaded into memory from the corresponding “.class” bytecode file.

(2) Verification stage

Simply put, this step verifies that the contents of the loaded “.class” file conform to the specified specification against the Java virtual machine specification.

For example, if your “.class “file is tampered with and contains bytecodes that do not conform to the specification, the JVM will not be able to execute the bytecodes.

So once the bytecode file has been loaded into memory, it must be verified and fully compliant with JVM specifications before it can be handed over to the JVM.

(3) Preparation stage (core)

After validation verifies that the bytecode file contents conform to the specification, the preparation phase begins.

public class Demo {
 
    public static int number;
 
}
Copy the code

Suppose there is the above code. The preparation is simply to allocate some memory space to the “Demo” class;

The static variable number is allocated with a default initial value of 0.

The whole process is as follows:

In the three stages of verification, preparation and analysis, the preparation stage is the core.

Because this phase allocates memory for the loaded class, the class variables also allocate memory and give default initial values.

(4) Analysis stage

This phase, which is actually the process of replacing symbolic references with direct references, involves the underlying JVM and is not interpreted at this stage.

(5) Core stage: initialization

In preparation, the class memory is allocated and the class variable is given a default initial value of 0, so the next step is the code that performs the class initialization.

public class Demo {
 
    public static int number = 5;
    
}
Copy the code

As you can see, 5 is assigned to the class variable number, but is it assigned in preparation?

It won’t. The preparation phase simply creates a memory space for the number class variable and gives it an initial value of “0”.

The assignment code is executed in the “initialization” phase.

Static blocks of static code are also executed at this stage.

When is a class initialized?

In general, if “new Demo()” is used to instantiate the object of the class, then the loading and initialization process will be triggered. The class is ready, and then an object will be instantiated.

Or a main class that contains a “main” method, which must be initialized immediately.

A very important rule is that if a class is initialized and its parent is not initialized, it must initialize its parent first, as in the following code:

public class Demo extends DemoFather{
 
    public static int number = 5;
    
}
Copy the code

If you want to “new Demo ()”, the class will be loaded and initialized, but before initializing the class, find “DemoFather” as the parent class has not been loaded and initialized, so you must first load the parent class and initialize the parent class.

Class loaders and parent delegate mechanisms

To achieve the above process, must rely on the class loader to achieve;

Java simply has the following types of loaders:

(1) Start the class loader

Bootstrap ClassLoader, which is mainly responsible for loading the core classes in the Java directory we installed on the machine.

In the Java installation directory, there is a “lib” directory, which contains some of the most core Java class libraries, supporting the running of the Java system.

Once the JVM is started, it first loads the core libraries in the “lib” directory of the Java installation directory, relying on the startup class loader.

(2) Extend the class loader

Extension ClassLoader is a Java installation directory with a “lib\ext” directory.

There are some classes that need to be loaded using the class loader to support the system.

Once the JVM is started, the classes for that directory must also be loaded from the Java installation directory.

(3) Application loader

Application Classloader, which assists in loading classes at the path specified by the “ClassPath” environment variable

To load your Javadiam, the classloader takes care of loading your classes into memory.

(4) Custom class loaders

Load your classes according to your own needs.

(5) Parent delegation mechanism

The JVM class loaders have a parent-child hierarchy, meaning that the launcher class loaders are at the top, the extension class loaders are at the second, the application loaders are at the third, and the custom class loaders are at the last.

As shown in the figure:

Based on this parent-child hierarchy, there is a mechanism for parental delegation.

Is assuming your application loader need to load a class, it is first assigned to its parent class loader for the, eventually reached to the top of the class loader to load, but if the parent class loader is responsible for the scope of the load in himself, did not find the class, so will be pushed down loaded right to own the class loader.

For example, if your JVM now needs to load the “DemoMain” class, the application classloader will ask its parent, the extension classloader, can you load this class?

And then the extension class loader says to his dad, start the class loader, can you load this class?

Start the classloader thinking, “I can’t find this class in the Java installation directory.

Then, the extension class loader is pushed down the load right to the son of the extension class loader, the result of the extension class loader looked for a long time, but did not find their responsible directory has this class

At this point, he will be angry and say: you are clearly responsible for the application loader, go find it yourself.

Then the application class loader is responsible for its scope, such as the jar package that you wrote the system into, suddenly found, here! Then I load the class into memory myself.

This is known as the parent-delegate model: the father loads it, and the son loads it if it doesn’t work.

This way, you can avoid a multi-tiered loader structure that reloads certain classes.

The last

Thank you for reading here. If you don’t understand anything, please ask me in the comments section. If you think this article is helpful to you, please give me a thumbs up.