What is ClassLoader? As we all know, when we write a Java program, it is not CS or BS application, is composed of several. Class files organized into a complete Java application, when the program is running, that is, it will call an entry function of the program to call the related functions of the system. These functions are encapsulated in different class files, so it is often necessary to call methods from one class file to another. If the other class file does not exist, a system exception will be raised. When the program is started, it does not load all the class files used by the program at one time. Instead, it dynamically loads a class file into the memory through the Java ClassLoader according to the needs of the program. Only the class file is loaded into the memory. Can be referenced by other classes. So the ClassLoader is used to dynamically load class files into memory. Java provides three classLoaders by default

  1. BootStrap ClassLoader: is the top ClassLoader in the Java class loading hierarchy. It is responsible for loading the core class libraries in the JDK, such as: Jar, resources.jar, charsets. Jar, etc., can be used to find out where the class loader loaded the relevant JAR or class file:
URL[] urls = sun.misc.Launcher.getBootstrapClassPath().getURLs();  
for(int i = 0; i < urls.length; i++) { System.out.println(urls[i].toExternalForm()); } The following is what the above program gets from the native JDK environment: File: / C: / Program files/Java / % 20 jdk1.6.0 _22 / jre/lib/resources. The jar File: / C: / Program files/Java / % 20 jdk1.6.0 _22 / jre/lib/rt. The jar File: / C: / Program files/Java / % 20 jdk1.6.0 _22 / jre/lib/sunrsasign. The jar File: / C: / Program files/Java / % 20 jdk1.6.0 _22 / jre/lib/jsse. Jar file: / C: / Program files/Java / % 20 jdk1.6.0 _22 / jre/lib/jce jar File: / C: / Program files/Java / % 20 jdk1.6.0 _22 / jre/lib/charsets. Jar file: / C: / Program files/Java / % 20 jdk1.6.0 _22 / jre/classes /Copy the code

In fact, the above results are also found by looking for the system property sun.boot.class.path. System.out.println(System.getProperty(“sun.boot.class.path”));

C: Program Files\Java\jdk1.6.0_22\jre\lib\resources. C: \ Program Files \ Java \ jdk1.6.0 _22 \ jre \ lib \ rt jar; C: \ Program Files \ Java \ jdk1.6.0 _22 \ jre \ lib \ sunrsasign jar; C: \ Program Files \ Java \ jdk1.6.0 _22 \ jre \ lib \ jsse jar; C: \ Program Files \ Java \ jdk1.6.0 _22 \ jre \ lib \ jce jar; C: \ Program Files \ Java \ jdk1.6.0 _22 \ jre \ lib \ charsets jar; C: \ Program Files \ Java \ jdk1.6.0 _22 \ jre \ classesCopy the code
  1. Extension ClassLoader: is called extension class loader, responsible for loading Java extension class libraries, the default loadJAVA_HOME/jre/lib/ext/All jars below.
  2. App ClassLoader: is called the system class loader and is responsible for loading applicationsclasspathAll jar and class files in the directory. Note: In addition to the three classLoaders provided by default in Java, users can also define their own classloaders as needed, and these custom classloaders areMust inheritFrom the java.lang.ClassLoader class, including two other Classloaders provided by Java (Extension ClassLoader and App ClassLoader), However, Bootstrap ClassLoader does not inherit from ClassLoader, because it is not a common Java class. The bottom layer is written by C++ and has been embedded into the JVM kernel. When the JVM starts, Bootstrap ClassLoader starts with it. After loading the core class library, construct Extension ClassLoader and App ClassLoader. The principle of ClassLoader to load a class
1. Principle introduction

The parental delegation model works like this: if a class loader receives a request for a class load, it first does not try to load the class itself, but delegates the request to the parent class loader. This is true for every classloader, and only if the parent cannot find the specified class in its search scope (that is, ClassNotFoundException) will the child loader attempt to load it itself.

Each ClassLoader instance has a reference to a parent ClassLoader (not an inherited relationship, but a contained relationship). The Bootstrap ClassLoader does not have a parent ClassLoader itself. But can be used as a parent ClassLoader for other ClassLoader instances. When a ClassLoader instance needs to load a class, it will try to search for the class itself and delegate this task to its parent ClassLoader. The process is checked from top to bottom. Bootstrap ClassLoader, the top ClassLoader, tries to load the class. Then the task will be handed over to the Extension ClassLoader for loading. If it is not loaded, it will be handed over to the App ClassLoader for loading. If it is not loaded, it will be returned to the initiator of the delegate, and it will load the class in the specified FILE system or network URL. If none of them are loaded into the class, a ClassNotFoundException is thrown. Otherwise, the found Class generates a Class definition, loads it into memory, and returns an in-memory Class instance object of the Class. #####2. Why use the parental delegation model? Because this avoids double loading, there is no need for the child ClassLoader to load the class again when the parent has already loaded the class. For security reasons, we can imagine that without this delegate pattern, we could use a custom String to dynamically replace the type defined in the Java core API at any time. This would be a huge security risk. Since strings are already loaded by the Bootstrcp ClassLoader at startup, a user-defined ClassLoader will never load a self-written String unless you change the default algorithm for ClassLoader searching classes in the JDK. #####3. But how does a JVM determine that two classes are the same when searching for them? When determining whether two classes are identical, the JVM determines not only whether they have the same class name, but also whether they are loaded by the same classloader instance. The JVM considers two classes to be the same only if they both satisfy. Even if two classes are the same class bytecode, if they are loaded by two different ClassLoader instances, the JVM will treat them as two different classes. Such as a Java class ClassLoaderSimple org.classloader.simple.Net on the network, after the javac compiler to generate the bytecode file NetClassLoaderSimple. Class, ClassLoaderA and ClassLoaderB these two class loaders and read the NetClassLoaderSimple. Class files, and define the Java respectively. Lang. To represent the class, the class instance for the JVM, they are two different instance objects, They are really the same bytecode file, if you try to put this Class instance to generate specific object transform, Java runtime exception will be thrown. Lang. ClassCaseException, suggest they are two different types. Now through examples to verify the above described is correct: 1), on a web server to build an org.classloader.simple.Net ClassLoaderSimple. Java classes

package org.classloader.simple;  
  
public class NetClassLoaderSimple {  
      
    private NetClassLoaderSimple instance;  
  
    public void setNetClassLoaderSimple(Object obj) { this.instance = (NetClassLoaderSimple)obj; }}Copy the code

Org.classloader.simple.Net ClassLoaderSimple class setNetClassLoaderSimple method takes an Object type parameters, And will it casts into org.classloader.simple.Net ClassLoaderSimple types. 2) Test whether two classes are the same (networkClassloader.java)

package classloader; Public class NewworkClassLoaderTest {public static void main(String[] args) {try {// Test load network class file String rootUrl ="http://localhost:8080/httpweb/classes";  
            String className = "org.classloader.simple.NetClassLoaderSimple"; NetworkClassLoader ncl1 = new NetworkClassLoader(rootUrl); NetworkClassLoader ncl2 = new NetworkClassLoader(rootUrl); Class<? > clazz1 = ncl1.loadClass(className); Class<? > clazz2 = ncl2.loadClass(className); Object obj1 = clazz1.newInstance(); Object obj2 = clazz2.newInstance(); clazz1.getMethod("setNetClassLoaderSimple", Object.class).invoke(obj1, obj2); } catch (Exception e) { e.printStackTrace(); }}}Copy the code

First, obtain the binary name of a class file on the network. Then, create two instances of the class using the custom NetworkClassLoader, and load the class according to the network address. Clazz1 and clazz2 are generated after the two ClassLoader instances are loaded. Finally, obj1 and obj2 are generated from these two Class instances respectively. The setNetClassLoaderSimple method in Clazz1 is then called through reflection. 3) View the test results

Conclusion: You can see from the results that although the same class bytecode file is loaded by two different ClassLoader instances, the JVM considers them to be two different classes.

Test 1: Print the ClassLoader class hierarchy. Look at this code:

ClassLoader loader = ClassLoaderTest.class.getClassLoader(); // Get the classloader that loads classLoadertest. classwhile(loader ! = null) { System.out.println(loader); loader = loader.getParent(); } system.out.println (loader);Copy the code

Print result:

Test 2

The second line is null because the parent of the ExtClassLoader is Bootstrap ClassLoader. Test 3: Use Bootstrcp ClassLoader to load classLoadertest. class in two ways: Add the -xbootclasspath parameter to the JVM to specify the path where the Bootstrcp ClassLoader loads the class. Append our own jar (classtestLoader.jar) to JAVA_HOME/jre/classes/ (I use Eclipse development tools and add -xbootCLASspath to the Java command on the command line.)

[java.io.FileReader from C: Program Files\Java\jdk1.6.0_22\jre\lib\rt.jar] [Loaded java.io.FileReader from C: Program Files\Java\jdk1.6.0_22\jre\lib\rt.jar C: Program Files\Java\jdk1.6.0_22\jre\lib\rt.jar] [Loaded java.util Files\Java\jdk1.6.0_22\jre\lib\rt.jar] [Loaded java.lang.reflect.Array from C: Program Files\Java\jdk1.6.0_22\jre\lib\rt.jar] [Loaded java.util.Locale from C:\Program Files\Java\jdk1.6.0_22\jre\lib\rt.jar] Loaded java.util.Locale from C:\Program Files\Java\jdk1.6.0_22\jre\lib\rt.jar [the Loaded Java. Util. Concurrent. The ConcurrentMap from C: \ Program Files \ Java \ jdk1.6.0 _22 \ jre \ lib \ rt jar] [the Loaded Java. Util. Concurrent. ConcurrentHashMap from C: \ Program Files \ Java \ jdk1.6.0 _22 \ jre \ lib \ rt jar] [the Loaded Java. Util. Concurrent. The locks. Lock the from C: \ Program Files \ Java \ jdk1.6.0 _22 \ jre \ lib \ rt jar] [the Loaded Java. Util. Concurrent. The locks. Already the from C: \ Program Files \ Java \ jdk1.6.0 _22 \ jre \ lib \ rt jar] [the Loaded java.util.concurrent.ConcurrentHashMap$SegmentThe from C: \ Program Files \ Java \ jdk1.6.0 _22 \ jre \ lib \ rt jar] [the Loaded Java. Util. Concurrent. The locks. AbstractOwnableSynchronizer The from C: \ Program Files \ Java \ jdk1.6.0 _22 \ jre \ lib \ rt jar] [the Loaded Java. Util. Concurrent. The locks. AbstractQueuedSynchronizer The from C: \ Program Files \ Java \ jdk1.6.0 _22 \ jre \ lib \ rt jar] [the Loaded Java. Util. Concurrent. The locks. Already$SyncThe from C: \ Program Files \ Java \ jdk1.6.0 _22 \ jre \ lib \ rt jar] [the Loaded Java. Util. Concurrent. The locks. Already$NonfairSyncThe from C: \ Program Files \ Java \ jdk1.6.0 _22 \ jre \ lib \ rt jar] [the Loaded Java. Util. Concurrent. The locks. AbstractQueuedSynchronizer$NodeThe from C: \ Program Files \ Java \ jdk1.6.0 _22 \ jre \ lib \ rt jar] [the Loaded Java. Util. Concurrent. ConcurrentHashMap$HashEntryThe from C: \ Program Files \ Java \ jdk1.6.0 _22 \ jre \ lib \ rt jar] [the Loaded Java. Lang. CharacterDataLatin1 from C: \ \ Program Files \ Java \ jdk1.6.0 _22 \ jre \ lib \ rt jar] [the Loaded Java. IO. ObjectStreamClass from C: \ \ Program Files\Java\jdk1.6.0_22\jre\lib\rt.jar] [Loaded sun.net.www.ParseUtil from C: Program Files\Java\jdk1.6.0_22\jre\lib\rt.jar] [Loaded java.util.BitSet from C:\Program Files\Java\jdk1.6.0_22\jre\lib\rt.jar] Loaded java.util.BitSet from C:\Program Files\Java\jdk1.6.0_22\jre\lib\rt.jar [the Loaded java.net.Parts from C: \ Program Files \ Java \ jdk1.6.0 _22 \ jre \ lib \ rt jar] [the Loaded java.net.URLStreamHandler the from C: \ Program Files \ Java \ jdk1.6.0 _22 \ jre \ lib \ rt jar] [the Loaded sun.net.www.protocol.file.Handler from C: \ \ Program Files\Java\jdk1.6.0_22\jre\lib\rt.jar] [Loaded java.util.HashSet from C:\Program Files\Java\jdk1.6.0_22\jre\lib\rt.jar] Loaded java.util.HashSet from C:\Program Files\Java\jdk1.6.0_22\jre\lib\rt.jar [the Loaded sun.net.www.protocol.jar.Handler from C: \ Program Files \ Java \ jdk1.6.0 _22 \ jre \ lib \ rt jar] [the Loaded sun.misc.Launcher$AppClassLoaderFrom C: Program Files\Java\jdk1.6.0_22\jre\lib\rt.jar] [Loaded sun.misc.Launcher$AppClassLoaderThe $1The from C: \ Program Files \ Java \ jdk1.6.0 _22 \ jre \ lib \ rt jar] [the Loaded Java. Lang. SystemClassLoaderAction from C: \ \ Program Files\Java\jdk1.6.0_22\jre\lib\rt.jar] [Path C:\Program Files\Java\jdk1.6.0_22\jre\classes] [Loaded This. ClassLoaderTest from C: \ Program Files \ Java \ jdk1.6.0 _22 \ jre \ classes] null / / C: this is the result of print \ Program Files \ Java \ jdk1.6.0 _22 \ jre \ lib \ resources jar; C: \ Program Files \ Java \ jdk1.6.0 _22 \ jre \ lib \ rt jar; C: \ Program Files \ Java \ jdk1.6.0 _22 \ jre \ lib \ sunrsasign jar; C: \ Program Files \ Java \ jdk1.6.0 _22 \ jre \ lib \ jsse jar; C: \ Program Files \ Java \ jdk1.6.0 _22 \ jre \ lib \ jce jar; C: \ Program Files \ Java \ jdk1.6.0 _22 \ jre \ lib \ charsets jar; C: \ Program Files \ Java \ jdk1.6.0 _22 \ jre \ classes; C :\ classLoadertest.jar // This is system.out.println (system.getProperty ())"sun.boot.class.path")); It's printed out. Loaded java.lang.Shutdown from C:\Program Files\Java\jdk1.6.0_22\jre\lib\rt.jar [Loaded java.lang.Shutdown$LockThe from C: \ Program Files \ Java \ jdk1.6.0 _22 \ jre \ lib \ rt jar]Copy the code

Method 2: Decompress classloadertest. jar and put it in JAVA_HOME/jre/classes, as shown in the following figure: Tip: There is no classes directory in the JRE directory by default. You need to create one yourself

Update custom ClassLoader tomorrow