1. Parental delegation model

We know that class loading mechanism is the process of converting a class from a bytecode file to a virtual machine that can use the class directly. But who performs the loading process and how does it complete or guarantee the accuracy and security of class loading? The answer is class loaders and parental delegation.

The parent delegate model works like this: when a class loader receives a request for a class load, it does not try to load the class itself. Instead, it delegates the request to the parent loader, and the child loader tries to load the class itself only when the parent loader reports that it is unable to complete the request.

You can see how it works in the JDK source code.

ClassLoader#loadClass(String,boolean)

This is the source code in the java.lang.ClassLoader class of JDK1.8, which is used to load the specified class.

protected Class<? > loadClass(String name, boolean resolve) throws ClassNotFoundException { synchronized (getClassLoadingLock(name)) { // First, Check if the class has already been loaded // First check if the class has already been loaded by the current class loader. > c = findLoadedClass(name); if (c == null) { long t0 = System.nanoTime(); try { if (parent ! = null) { c = parent.loadClass(name, false); } else { c = 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. Long t1 = system.nanotime (); c = findClass(name); // this is the defining class loader; record the stats sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0); sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); sun.misc.PerfCounter.getFindClasses().increment(); } } if (resolve) { resolveClass(c); } return c; }}Copy the code

Conclusion can be drawn from the above code:

  • When the classloader receives a classloading request, it first checks whether the class has been loaded by the current classloader.
  • If the class has not been loaded, the current class loader delegates the loading request to the parent class loader.
  • If the parent class loader of the current class loader is NULL, the starting class loader is entrusted to complete the loading.
  • If the parent class loader cannot finish loading the class, the current class loader will attempt to load the class.

Class loader classification

Start the Bootstrap ClassLoader

The launcher ClassLoader, the granddaddy of all class loaders, is implemented by C++ and does not inherit the java.lang.ClassLoader class. It is loaded by a piece of C++ code from the virtual machine when the virtual machine starts up, so it has no parent class loader. Once loaded, it is responsible for loading the extension class loader and the application class loader.

The bootclass loader is used to load Java core classes in JAVA_HOME\lib, or in the path specified by the -xBootCLASspath parameter, and is a library recognized by the virtual machine.

Extension ClassLoader Extension ClassLoader

The extension ClassLoader inherits from the java.lang.ClassLoader class. Its parent is the launcher ClassLoader, which is null in Java.

From a comment on the jdk1.8 ClassLoader#getParent() method, which is used to get the parent of the classloader: Returns the parent class loader for delegation. Some implementations may use null to represent the bootstrap class Loader. This method will return null in such implementations if This class loader’s parent is the bootstrap class loader

The extension class loader is responsible for loading the class libraries in the JAVA_HOME\lib\ext directory, or in the path specified by the java.ext.dirs system variable.

Note: The extended class loader only supports loading bytecode files packaged in.jar format.

Application ClassLoader Application ClassLoader

The JVM loads classes through the parent delegate model, but we can also implement custom class loaders by inheriting java.lang.ClassLoader.

Custom ClassLoader Custom ClassLoader

The custom ClassLoader inherits from the java.lang.ClassLoader class, whose parent is the application ClassLoader.

This is a user-defined class loader that loads bytecode files in a specified path.

The custom ClassLoader inherits the java.lang.ClassLoader class and overwrites the findClass method to implement custom class loading logic.

Benefits of the parental delegation model

Based on this hierarchical relationship with priority specified by the parent delegate model, the virtual machine can run programs without reloading classes. When the parent Class loader has already loaded a Class, if another Class load request is passed to the subclass loader, the subclass loader executes the loadClass method and delegates it to the parent Class loader to try to load the Class, but the parent Class loader executes the Class<? > c = findLoadedClass(name); The phase of checking to see if the class has already been loaded checks that the class has already been loaded and returns to the class without reloading it.

The parental delegation model avoids core class tampering. The core classes we describe are rt.jar and tools.jar, which are loaded by the startup class loader. These libraries are widely used in daily development, and if tampered with, the consequences will be terrible.

Shortcomings of the parental delegation model

For historical reasons (the ClassLoader class existed in JDK1.0 and the parental delegation model was introduced after JDK1.2), without introducing the parental delegation model, User-defined classloaders need to inherit the java.lang.ClassLoader class and override the loadClass() method, because the virtual machine calls ClassLoader#loadClassInternal(String) when loading the class. This method (source below) calls the loadClass() method overridden by custom class loading. With the introduction of the parent delegate model, the ClassLoader#loadClass method is actually an implementation of the parent delegate model. If you rewrite this method, you break the parent delegate model. In order for user-defined classloaders to also comply with the parental delegation model, the JDK added the findClass method to implement custom classloading logic.

private Class<?> loadClassInternal(String name) throws ClassNotFoundException{
	 // For backward compatibility, explicitly lock on 'this' when
	 // the current class loader is not parallel capable.
	 if (parallelLockMap == null) {
		 synchronized (this) {
		 	return loadClass(name);
		 }
	 } else {
	 	return loadClass(name);
	 }
 }

Copy the code

Due to the hierarchical relationship stipulated by the parent delegate model, the classes loaded by the subclass loader can access the classes loaded by the parent class loader, while the classes loaded by the parent class loader cannot access the classes loaded by the subclass loader. To allow classes loaded by the upper class loader to access classes loaded by the lower class loader, or for the parent class loader to delegate loading requests to the subclass loader, the JDK introduced thread-context classloaders to break the barrier of the parent delegate model.

When the user needs the dynamic nature of the program, such as hot replacement of code, hot deployment of modules, etc., the parent delegate model is no longer suitable and class loaders evolve into more complex network structures.

conclusion

The last

At the end of the article the author sorted out a lot of information for you! Including Java core knowledge + a full set of architect learning materials and video + first-line factory interview treasure dictionary + resume template interview ali Meituannetease Tencent Xiaomi IQiyi Quick hand bilibili bilibili interview questions +Spring source code collection +Java architecture actual combat e-books and so on! Welcome to pay attention to the public number: the future has light, receive!