Java class loader (1)-Class Loader hierarchy and Model
Class Loader
?? The virtual machine design team put the "get and describe the binary byte stream of this class through the full qualified name of a class" action in the class loading stage outside the Java Virtual Machine for implementation, so that the application can decide how to obtain the required classes. The Code module that implements this action is called the class loader ".
Class Loader level (level)
?? From the JVM perspective, there are only two different class loaders.
?? The first type is to start the Class Loader (Bootstrap ClassLoader): This Class Loader mainly loads the class required for JVM's own work. This class loader is implemented by the C ++ language (especially HotSpot) and is part of the virtual machine itself. It is responsible for storing it in the % JAVA_HOME % \ lib directory, or in the path specified by the-Xbootclasspath parameter, and is recognized by virtual machines (only by file name, such as rt. jar, class libraries with invalid names are not loaded even in the lib directory.) the class is loaded into the VM memory.
?? The other type is all other class loaders, which are implemented by java and independent from external virtual machines.
??Extension ClassLoader: This class has sun. misc. launcher $ ExtClassLoader implementation, which is responsible for loading the % JAVA_HOME % \ lib \ ext directory, or by java. ext. all class libraries in the path specified by dirs system variables can be directly used by developers.
??Application ClassLoader: This class loader is implemented by sun. misc. Launcher $ AppClassLoader. Because this class loader is the return value of the getSystemClassLoader () method in ClassLoader, it is generally used as a system class loader. It is responsible for loading the specified class library on the user's class path. developers can directly use this class loader. If the application does not have a custom class loader, in general, this is the default class loader in the program.
?? The parent of AppClassLoader is ExtClassLoader. Many articles also include Bootstrap ClassLoader in the upper level of ExtClassLoader when introducing the hierarchical structure of ClassLoader. In fact, Bootstrap ClassLoader does not belong to the class level of JVM, because Bootstrap ClassLoader does not comply with the loading unit of ClassLoader. In addition, Bootstrap ClassLoader does not have a subclass. The parent class of ExtClassLoader is not Bootstrap ClassLoader, and ExtClassLoader does not have a parent class. The top-level parent class we can extract in the application is ExtClassLoader.
Code example:
ClassLoader cl = Thread.currentThread().getContextClassLoader(); System.out.println(cl.toString()); System.out.println(cl.getParent()); System.out.println(cl.getParent().getParent());
?? Output result:
[email protected][email protected]null
How to obtain ClassLoaderthis. getClass (). getClassLoader (); // use the ClassLoader Thread of the current class. currentThread (). getContextClassLoader (); // use the ClassLoader of the current thread. getSystemClassLoader (); // use the system ClassLoader
?? Code example:
public void test() { System.out.println(this.getClass().getClassLoader().toString()); System.out.println(Thread.currentThread().getContextClassLoader()); System.out.println(ClassLoader.getSystemClassLoader()); }
?? Output:
[email protected][email protected][email protected]
[Tips] How to obtain class attributes of a class:
1. Class. forName (full name of the Class path );
2. this. getClass ();
3. Use. class, such as String. class
4. For basic data types: Class c1 = int. class (class is only a convention mark, not a member attribute) or Class c2 = Integer. TYPE
?? There are two methods for JVM to load class files to memory:
?? 1. Implicit loading: the so-called implicit loading means to automatically load the required classes to the memory instead of calling ClassLoader in the code. For example, when we integrate or reference a class in a class, when JVM parses the current class and finds that the referenced class is not in the memory, it will automatically load these classes into the memory.
?? 2. display loading: the opposite display loading means that we can call the ClassLoader class in the code to load a class. For example, call this. getClass. getClassLoader (). loadClass () or Class. forName (), or the findClass () method of ClassLoader implemented by ourselves.
Parent-Child Assignment Model
?? In addition to Bootstrap ClassLoader, the parent-class delegation model requires that all other class loaders have their own parent class loaders.Here, the parent-child relationship between class loaders is generally not implemented based on the inheritance relationship, but the code of the parent class loader is reused using the Composition relationship..
?? The Parent-parent delegation model is not a mandatory constraint model, but a type of Loader implementation method recommended by java designers to developers. In the java World, most class loaders follow this model, but there are exceptions. So far, the Parent-parent delegation model mainly shows 3 large "damaged" situations, which will be explained later.
?? The working process of the parent-child delegate model is: if a Class Loader receives a class load request, it will not try to load the class by itself first, instead, this request is delegated to the parent class loader. This is true for class loaders at each layer. Therefore, all loading requests should be finally transmitted to the top-layer startup class loader, only when the parent loader reports that the loading request cannot be completed (the required class is not found in the search range) Will the child loader attempt to load the request by itself.
?? The role of the parent-parent delegation mechanism is to prevent local replacement of the system jar package, because the search process starts from the bottom layer. Therefore, we generally use this mechanism for custom classloader. We only need to inherit java. lang. classLoader implements findclass. If more control is required, the custom classloader needs to override the loadClass method. For example, the loading process of tomcat is complicated, you can refer to other documents for more information.
?? The parental delegation model is very important to ensure the stable operation of java programs. The implementation is reflected in the loadClass () method of java. lang. ClassLoader, as shown below:
protected Class
loadClass(String name, boolean resolve) throws ClassNotFoundException { synchronized (getClassLoadingLock(name)) { // First, check if the class has already been loaded Class 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 // to find the class. 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; } }
?? The loadClass () method is loaded as follows:
?? 1. Call Class c = findLoadedClass (name); to check whether the Class has been loaded;
?? 2. Call the loadClass method on the parent Class Loader:
??? C = parent. loadClass (name, false );
?? If the parent class loader is null, use the built-in class loader of the VM:
??? C = findBootstrapClassOrNull (name );
?? 3. When the parent class loader cannot be loaded, call its findClass method to load the class:
??? C = findClass (name );
The process for each ClassLoader to load a Class is as follows:
1. check whether this Class has been loaded (that is, whether this Class exists in the cache). If there is 8, if not;
2. If the parent classloader does not exist (there is no parent, the parent must be the bootstrap classloader), to 4;
3. Request the parent classloader for loading. If it succeeds to 8, it fails to 5;
4. Request the jvm to load from the bootstrap classloader. If it succeeds, it will be 8;
5. Search for the Class file (from the Class path related to this classloader ). 7 if not found;
6. Load the Class from the file to 8;
7. Throw ClassNotFoundException;
8. Return Class.
Destroys the Parent-Child Delegation Model
?? As mentioned above, the parent-parent delegation model has been damaged for three times so far.
?? The first time. Occurs before the Parent-Child delegation model appears (before jdk1.2 is released ). Because the Parent-Child delegation model is introduced only after jdk1.2, the class loader and the abstract class java. lang. classLoader already exists in the jdk1.0 era. In the face of the existing user-defined ClassLoader implementation code, java designers had to make some compromises when introducing the parent-parent delegation model. History has become a thing of the past. Here we will not repeat it here. It should be noted that after jdk1.2, we do not recommend that users overwrite the loadClass () method, but should write their own class loading logic to findClass () to ensure that the rules of the parent-child delegation model are met.
?? The second time. Due to the defects of the model itself, the parent-parent delegation model solves the unified problem of the basic classes of each class loader. When the parent class loader needs to request the subclass loader to complete the class loading action, for example, the JNDI service: its code is loaded by the startup class loader, however, the purpose of JNDI is to centrally manage and search resources. It needs to call the code of the JNDI provider (SPI) implemented by an independent vendor and deployed under the Classpath of the application, however, the Class Loader does not recognize the code. This requires the use of the Thread Context loader (Thread Context ClassLoader ). This class loader can be set through the setContextClassLoader () method of the java. lang. Thread class.
?? How can we create another context classloader? What is its use? When we create a Thread, we can use the setContextClassLoader method to specify a suitable classloader as the context classloader of the Thread. When this Thread is running, we can use the getContextClassLoader method to obtain the context classloader and use it to load the Class we need. The default value is system classloader. With this feature, we can "break" The classloader delegation mechanism. The parent classloader can obtain the context classloader of the current thread, and the context classloader can be its sub-classloader or other classloader, then, the parent classloader can obtain the required Class from it, which breaks the restrictions that can only be requested from the parent classloader. This mechanism can meet the requirements of system classloader (that is, in jvm classpath) when our classpath is determined at runtime and loaded by the custom classloader) you can use the context classloader to obtain the custom classloader and load it into a specific class (usually abstract classes and interfaces, which are implemented in the Custom classloader ), for example, servlets in web applications are loaded using this mechanism.
?? The third time. Due to users' pursuit of program dynamics, the "dynamic" mentioned here refers to some very "popular" names: Code hot replacement, module hot deployment, etc, it is similar to hot plugging of the mouse and keyboard. For details, let's take a look at OSGi. In the OSGi environment, the class loader is no longer a tree structure in the parent-parent delegate model, but a mesh structure. For details, refer to some relevant materials.