JVM class loading mechanism and parent delegation mechanism

The class loading order is as follows:

Load -> Validate -> Prepare -> Parse -> Initialize

loading

The bytecode file is found on the hard disk and read through IO. It will be loaded only when the Class is used, such as calling the main() method of the Class, creating an object, etc. When loading the pair, a Class object representing the Class will be generated in memory, which will serve as the access point for various data of the Class in the method area

validation

Check the correctness of bytecode, prevent bytecode tampering.

To prepare

Allocates memory to static variables of the class and assigns default values

parsing

This phase replaces some static methods (symbolic references, such as the main() method) with Pointers or handles to the memory where the data is stored (direct references). This is the process of static linking. Dynamic linking converts symbolic references to direct references while the program is running

Initialize the

Executes a static code block by initializing a static variable of the class to the specified value

Class loaders and parent delegation mechanisms

Class loader

  • The Bootstrap ClassLoder is responsible for loading the core library classes that support the JVM, which are located in the JRE’s lib directory.
  • Extension ClassLoader: The Extension ClassLoader is responsible for loading the JAR packages in the Ext Extension directory under the JRE lib that support the JVM
  • Application ClassLoader: Is responsible for loading the class packages in the Classpath. It mainly loads the classes written by itself
  • User ClassLoader: Loads class packages in user-defined paths

Parent delegation mechanism

JVM class loaders have a parent and child hierarchy, as shown below:

The simplest way to understand the parent delegate mechanism is that when a class is first loaded, it is first loaded by the parent, and then by the child

It is important to note that the parent loader is not directly inherited through the extend keyword, but rather the value of the attribute. As shown in figure:

The loadClass method of the ClassLoader implements the parent delegation mechanism

 protectedClass<? > loadClass(String name,boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // First, check if the class has already been loaded 
            // First, check whether the class is loaded by the current class loaderClass<? > c = findLoadedClass(name);if (c == null) { // The class is not loaded
                long t0 = System.nanoTime();
                try {
                    if(parent ! =null) { // Delegate the class to the parent loader if the current parent loader is not empty
                        c = parent.loadClass(name, false);
                    } else {  // Delegate to bootstrap the classloader to load the class if the current parent loader is nullc = findBootstrapClassOrNull(name); }}catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }
				// 
                if (c == null) {
                    // If still not found, then invoke findClass in order
                    // to find the class.
                    long t1 = System.nanoTime();
                    c = findClass(name);

                    // this is the defining class loader; record the statssun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0); sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); sun.misc.PerfCounter.getFindClasses().increment(); }}if (resolve) {
                resolveClass(c);
            }
            returnc; }}Copy the code

Why design a parent delegate mechanism?

Sandbox security: self-written Java.lang.string. class classes are not loaded, thus preventing the core

The API library was tampered with

Avoid class duplication: There is no need for a child ClassLoader to load a class when the parent has already loaded the class

To ensure the uniqueness of the loaded class


How do I break parent delegation

Inherits the ClassLoader class, overwrites the loadClass method, implements its own load logic, and does not delegate the load to the parent loader.

Tomcat breaks the parent delegation mechanism

In the case of Tomcat class loading, can Tomcat use the default parent delegate class loading mechanism?

Let’s think about this: Tomcat is a Web container, so what problem is it trying to solve:

  1. A Web container may need to deploy two applications, and different applications may depend on the same third-party class library

Different versions, cannot require the same library on the same server only one copy, so to ensure that each application class library is

Independent, guaranteed isolation from each other.

  1. The same version of the same class library deployed in the same Web container can be shared. Otherwise, if the server has 10 applications

Order, so there must be 10 copies of the same library loaded into the virtual machine.

  1. The Web container also has its own dependent class libraries that should not be confused with the application’s class libraries. For security reasons, the container should be

The class library is isolated from the program’s class library.

  1. For the Web container to support JSP modifications, we know that JSP files eventually have to be compiled into class files to be in the virtual machine

But modifying JSPS after the program is running has become commonplace, and the Web container needs to support JSP changes without restarting.

Let’s look at our question: Can Tomcat use the default parent delegate classloading mechanism?

The answer is no. Why is that?

The first problem is that if you use the default classloader mechanism, you will not be able to load two different versions of the same class library by default

The class adder is a single copy of your fully qualified class name regardless of your version.

The second problem is that the default classloader is possible because its job is to ensure uniqueness.

The third question is the same as the first.

Let’s look at the fourth problem, and we want to know how we can implement the hot loading of JSP files, which are actually class files

If the class name remains the same, the class loader will simply take the modified JSP that already exists in the method area

It’s not going to reload. So what to do? We can just unload the class loader for this JSP file, so you should think

Each JSP file corresponds to a unique classloader, and when a JSP file is modified, the JSP class load is directly unloaded

Device. Recreate the classloader and reload the JSP file.

Tomcat custom loader details

There are several main class loaders for Tomcat:

CommonLoader: The most basic class loader for Tomcat. Classes in the load path can be used by Tomcat

The app itself and access to various WebApps;

CatalinaLoader: Private class loader for the Tomcat container. Classes in the loading path are not available for Webapp

Visible;

SharedLoader: a class loader shared by each Webapp, with classes in the load path for all

Webapp is visible, but not to the Tomcat container;

WebappClassLoader: private class loader for each Webapp. The class in the loading path is only for the current class

Each war package application has its own WebappClassLoader, which can be isolated from each other. For example, different WAR package applications introduce different versions of Spring.

This allows implementations to load their respective versions of Spring;

From the delegate relationship in the figure, you can see:

Any classes that can be loaded by CommonClassLoader can be used by CatalinaClassLoader and SharedClassLoader,

CatalinaClassLoader and SharedClassLoader can load their own classes

Separate from each other.

WebAppClassLoader can use SharedClassLoader to load classes, but individual WebAppClassLoaders

Instances are isolated from each other.

JasperLoader’s loading scope is only the one compiled by this JSP file. Class file, the purpose for which it appears

Just to be discarded: When the Web container detects that the JSP file has been modified, it replaces the current JasperLoader instance,

And through the establishment of a new Jsp class loader to achieve the Jsp file hot loading function.

Does Tomcat’s classloading mechanism violate Java’s recommended parent delegation model? The answer is: no.

Obviously, this is not the way Tomcat is implemented. Tomcat, in order to achieve isolation, does not follow this convention

WebappClassLoader loads class files in its own directory and does not pass them to the parent class loader, breaking the parent committee

Send the mechanism