Parent delegation model and class loader

Write first

We all know that classes are loaded into the virtual machine through a class loader. What kind of class loader is there? What class loader is used to load the code we usually write into the virtual machine? What is the working mode of the class loader? Let's learn about the parent delegation model and class loader with questions.

1. Class Loader

1. What is a class loader

We all know that there are 7 main steps in the life cycle of a java file. The first step is to "get the binary byte stream describing the class through the fully qualified name". The code that implements this action is the "class loader".

2. The role of class loader

  1. Loading the class into the virtual machine is also the function point of the class loader.
  2. Used to distinguish type information. Two conditions must be met in the virtual machine to determine whether two types of information are equal. First, the class must be the same class, and second, the class loader that loads them must also be the same, otherwise the two classes are still not equal of. Let's implement a class loader ourselves to load a class, and then compare it with the class loaded by the system using the default loader.
    public class TestClassLoader {
          
          
        public static void main(String[] args){
          
          
            ClassLoader classLoader = new ClassLoader() {
          
          
                @Override
                public Class<?> loadClass(String name) throws ClassNotFoundException {
          
          
    
                    try {
          
          
    
                        InputStream in = getClass().getResourceAsStream(name.substring(name.lastIndexOf(".")+1)+".class");
                        if (in == null){
          
          
                            return super.loadClass(name);
                        }
                        byte[] by = new byte[in.available()];
                        in.read(by);
                        return defineClass(name,by,0,by.length);
                    } catch (IOException e) {
          
          
                        e.printStackTrace();
                        throw new ClassNotFoundException("类未找到");
                    }
                }
            };
    
            try {
          
          
                Object obj = classLoader.loadClass("sgcc.supplier.pojo.model.queues.TestClassLoader").newInstance();
                System.out.println(obj.getClass());
                System.out.println(new TestClassLoader().getClass());
    
                System.out.println(obj instanceof sgcc.supplier.pojo.model.queues.TestClassLoader);
                System.out.println(new TestClassLoader() instanceof sgcc.supplier.pojo.model.queues.TestClassLoader);
    
            } catch (InstantiationException e) {
          
          
                e.printStackTrace();
            } catch (IllegalAccessException e) {
          
          
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
          
          
                e.printStackTrace();
            }
        }
    
    }
    
    The above code implements a simple class loader, we use this class loader to load the current class, and then compared with the type loaded by the default loader, the result is as follows:
    class sgcc.supplier.pojo.model.queues.TestClassLoader
    class sgcc.supplier.pojo.model.queues.TestClassLoader
    false
    true
    
    Process finished with exit code 0
    
    
    From the output above, we can see that the type information of the new object loaded with our own class loader or the new object loaded with the default loader is exactly the same, and then we compare them with the type information and find that we loaded it ourselves. Is false, the default is true. So far, I have verified the above statement. Only the same type loaded by the same class loader is the same, otherwise they are not the same type. This feature of the class loader is also the meaning of the parent delegation model. You will know when you get off the card.

3. Common class loaders

  1. Bootstrap Class Loader (Bootstrap Class Loader)
    This launcher is implemented in C++ language and is mainly used to load classes under <JAVA_HOME>\lib (mainly in the form of jar packages). This class loader cannot be used directly by developers. It is also the only class loader that cannot be used directly by developers. Its main function is to load Java's own class library.

  2. Extension Class Loader (Extension Class Loader)
    uses java code to implement ExtClassLoader. This class is an extension class loader, inherited from ClassLoader, and is mainly used to load classes in the <JAVA_HOME>\lib\ext directory (mainly in the form of a jar package) ), this directory is a class library that supports the extension of the java class library. Users can put their own extended classes into this directory, and they will be loaded into the virtual machine by the extended class loader. Can be called directly. This class is implemented by java code and can be used directly by developers.

  3. Application Class Loader (Application Class Loader)
    uses java code to implement AppClassLoader This class is the application class loader, inherited from ClassLoader, mainly used to load all the class libraries on the user class path, if the class loader is not specified in the development , Then this class loader is used by default. In addition, the application class loader is sometimes referred to as the "system class loader".
    In addition to these three types of loaders, you can also define your own class loaders, which is also very simple. We only need to inherit the abstract class ClassLoader and implement the loadClass method.

2. Parental delegation model

1. Why do you need a parental delegation model

  1. Can
    we use one class loader to load all classes? We can find that there are roughly four types of class loader. The startup class loader is to load the java class library, the extended class loader is to load the extended class library, and the application class loader is this It is to load the classes we wrote ourselves. We can also implement the class loader by ourselves, so that there will be multiple class loaders. Can I load them all with one class loader? Why do you want to fix so much? The answer is definitely that you can't just use one class loader to load all classes. We have already said when we talked about the role of class loader. Class loader can also be used to distinguish types. The same class loaded by the same class loader will be considered the same class. If we write the same class as the java class library to use the same class loader, it is easy to change the basic classes provided by the java class library If it is messed up, it is not safe for the virtual machine, so there will be different class loaders to load class libraries for different scenarios.
  2. Can multiple class loaders load the same class?
    First of all, there is no problem with loading. Just like the role of class loaders mentioned earlier, the same class loaded by different class loaders will be recognized as different types. Suppose we Different class loaders are used to load the Object class, so when we use it, there is no way to compare whether the two objects are equal. Because they will not be equal anyway. So using multiple class loaders to load the same class is also unfriendly.
  3. Based on the above reasons, we need the "Parent Delegation Model".
    After reading the above two questions, I believe many people already understand that it is not practical to use one class loader to load all class libraries, and it is not feasible to use multiple class loaders to load class libraries at will. , So java introduced the "parental delegation model" in the 1.2 period.

2. What is the parent delegation model

The hierarchical relationship between class loaders as shown in the following figure is called the "parental delegation model", and the text description is: all class loaders should have their own parent class loaders, except for the top-level startup class loaders .
Insert picture description here

3. The working process of the parent delegation model

If a class loader receives a request for class loading, he does not load the class himself first, but in the future the class will be handed over to his parent class for loading, until it is passed to the startup class loader, if the startup class loader is loaded If it fails, it will tell the subclass loader that it is the subclass loader that will try to load it, and if it still fails, it will continue to hand it over to the subclass. The work flow of this piece will be well understood by cooperating with the loading range of each class loader. For example, it is an Object class, which belongs to the java class library for loading, so no matter which class loader receives the loading request, it will finally be handed over. It is loaded by the startup class loader. The startup class loader is loaded when it happens to be within my loading range. If it is a class written by ourselves, the startup class loader will not load it, and it will be given in the end. The application class loader is loaded.

4. Advantages of the parent delegation model

  1. The use of the parent delegation model will not cause the java class library to be tampered with, ensuring the security of the virtual machine.
  2. It is guaranteed that the same class will only be loaded once, and each class will have a hierarchical relationship with the loading of the class loader, and there will be no type disorder.

5. Destroy the parental delegation model

The parental delegation model is not a mandatory and restrictive model, but an implementation method of a class loader officially recommended to developers. We can also completely disregard this recommended model, knowing that until JDK9java modularization appears, parental delegation The model has been destroyed on a large scale three times.

  1. The first "break" was
    because the parental delegation model appeared in JDK1.2, and the class loader has appeared before this. Faced with the existing user-defined class loader code, the parental delegation model cannot be designed. Without making some compromises to be compatible with these existing codes, it is no longer possible to avoid the possibility of the loadClass method being overwritten by technical means. Only a pretected findClass method can be added, which is called when the parent class loader is called. Own class loading logic.

  2. The second time "destroy"
    through the workflow of the parent delegation model, we can find that the more basic the class, the closer the class loader will be to the startup class loader, because these classes are the easiest to be called, such as Object, InputStream and so on are all loaded by the startup class loader, so what if there is a basic type and the user code needs to be called? What class loader is used to load this basic type? So there is a Thread Context ClassLoader (Thread Context ClassLoader), this class loader will have one for each thread, you can use the setContextClassLoader in Thread to set, if not set, the parent thread will be used by default. If it is not set globally, the application class loader is used. This is a mode in which the parent class loader requests the child class loader to load the class, which is completely the opposite of the parent delegation model. This has been fixed in JDK6.

  3. The third "destruction"
    is that JDK9 introduces the modular system. The modular system requires that the java code can be replaced at will, just like peripheral devices, without restarting the system. This is the post-parent delegation model and it is no longer applicable. At this time, each module in the java system requires a class loader. When a module needs to be replaced, the module and its corresponding class loader are replaced together.

Full text summary

This article mainly introduces the general working mode of class loader and class loader. Parent delegation model. Before JDK9, we often used startup class loader, extended class loader (ExtClassLoaader), and application class loader (AppClassLoader). We also need to define our own class loader. These class loaders hierarchically load all the type information in the program we write into the virtual machine through the parent delegation model, ensuring the normal and effective execution of our code.

Guess you like

Origin blog.csdn.net/m0_46897923/article/details/114480671