Overview
ClassLoader's Parental delegation mode : ClassLoader is divided into three levels by level: Top: Bootstrap ClassLoader (root loader); Intermediate level: extension ClassLoader (Extension class loader) the lowest level app ClassLoader (app ClassLoader).
Root (Bootstrap) class loader : The loader does not have a parent loader. It is responsible for loading the virtual machine's core class libraries, such as java.lang.*. For example, Java.lang.Object is loaded by the root ClassLoader. The root ClassLoader loads the class library from the directory specified by the System Properties Sun.boot.class.path. The implementation of the root ClassLoader relies on the underlying operating system, which is part of the implementation of the virtual machine and does not inherit the Java.lang.ClassLoader class.
Extension (Extension) class loader : Its parent loader is the root class loader. It loads the class library from the directory specified by the Java.ext.dirs system property, or loads the class library from the Jre/lib/ext subdirectory (extended directory) of the JDK's installation directory, which is automatically loaded by the extension ClassLoader if the user-created jar file is placed in this directory. The extension class loader is a pure Java class and is a subclass of the Java.lang.ClassLoader class.
System class Loader : Also known as the Application class loader, its parent loader is the extension classloader. It loads the class from the environment variable classpath or the directory specified by the System Properties Java.class.path, which is the default parent loader for the user-defined ClassLoader. The System class loader is a pure Java class and is a subclass of the Java.lang.ClassLoader class.
The parent-child loader is not an inheritance relationship, meaning that the child loader does not necessarily inherit the parent loader.
For Java, Java virtual machines will be used to load Java class files through ClassLoader into the JVM memory, and this classloader is bootstrap ClassLoader. For the app, first request the app level to load, then request extension ClassLoader, and finally start Bootstrap ClassLoader.
Custom ClassLoader
Public class myclassloader extends ClassLoader { //class loader name PrivateString name;//Load the path of the class PrivateString Path ="d:/";Private FinalString FileType =". Class"; Public Myclassloader(String name) {//Let the System class loader be the parent loader for this ClassLoader Super(); This. name = name; } Public Myclassloader(ClassLoader parent, String name) {//Displays the parent loader that specifies the class loader Super(parent); This. name = name; } PublicStringGetPath() {returnPath } Public void SetPath(String Path) { This. Path = path; }@Override PublicStringtoString() {return This. Name; }Private byte[]Loaderclassdata(String name) {InputStream is =NULL;byte[] data =NULL; Bytearrayoutputstream BAOs =NewBytearrayoutputstream (); This. Name = This. Name.replace (".","/");Try{is =NewFileInputStream (NewFile (path + name + fileType));intc =0; while(-1! = (c = is.read ())) {baos.write (c); } data = Baos.tobytearray (); }Catch(Exception e) {E.printstacktrace (); }finally{Try{Is.close (); Baos.close (); }Catch(IOException e) {E.printstacktrace (); } }returnData }@Override PublicClass<?>Findclass(String name) {byte[] data = Loaderclassdata (name);return This. defineclass (name, data,0, data.length); } Public Static void Main(string[] args)throwsClassNotFoundException, Instantiationexception, illegalaccessexception {//loader1 's parent loader is the System class loaderMyclassloader Loader1 =NewMyclassloader ("Loader1"); Loader1.setpath ("d:/lib1/");//loader2 's parent loader is Loader1Myclassloader Loader2 =NewMyclassloader (Loader1,"Loader2"); Loader2.setpath ("d:/lib2/");//loader3 's parent loader is the root class loaderMyclassloader Loader3 =NewMyclassloader (NULL,"Loader3"); Loader3.setpath ("d:/lib3/"); Class clazz = Loader2.loadclass ("Sample"); Object object = Clazz.newinstance (); }} Public class Sample { Public Sample() {System.out.println ("Sample is loaded by"+ This. GetClass (). getClassLoader ());NewA (); }} Public class A { Public A() {System.out.println ("A is loaded by"+ This. GetClass (). getClassLoader ()); }}
Each custom ClassLoader must inherit the abstract class ClassLoader, and each ClassLoader will have a parent ClassLoader, We can take a look at ClassLoader. This abstract class has a getparent () method, which is used to return the parent of the current ClassLoader, noting that the parent is not referring to the inherited class, Instead, a ClassLoader is specified when the ClassLoader is instantiated, and if the parent is null, the parent of the ClassLoader is bootstrap Classloade.
The above explains the role of ClassLoader and the most basic loading process, and then we say that ClassLoader uses the parental delegate mode for class loading.
ClassLoader Parental delegation Mode
In layman's words, when a particular class loader receives a request to load a class, it first delegates the load task to the parent class loader, recursively, and returns if the parent ClassLoader can complete the class load task, only to load itself when the parent ClassLoader cannot complete the load task.
In order to better understand the parental delegation pattern, we first customize a classloader, assuming we use this custom ClassLoader to load the java.lang.String, then will the String be loaded by this classloader?
In fact java.lang.String This class is not loaded by our custom ClassLoader, but is loaded by bootstrap ClassLoader, why is this? This is actually the reason for the parental delegate mode, because before any of the custom ClassLoader loads a class, it will first delegate its father ClassLoader to load, and it will be loaded by itself only if the Father ClassLoader fails to load successfully. In the example above, because Java.lang.String is a class that belongs to the Java Core API, when you load it with a custom classloader, the ClassLoader will first delegate its father ClassLoader to load (bootstrap ClassLoader), so it will not be loaded by our custom ClassLoader.
Let's take a look at the source code of ClassLoader:
protected synchronizedClassLoadClass(String name,BooleanResolvethrowsclassnotfoundexception{//First check whether the class specified by the name has been loadedClass C = findloadedclass (name);if(c = =NULL) {Try{if(Parent! =NULL) {//If parent is not NULL, the loadclass of parent is called to loadc = Parent.loadclass (name,false); }Else{//parent is null, the Bootstrapclassloader is called to loadc = FINDBOOTSTRAPCLASS0 (name); } }Catch(ClassNotFoundException e) {//If it still fails to load successfully, call its own findclass to loadc = findclass (name); } }if(resolve) {Resolveclass (c); }returnC }
Advantages of using parental delegation mode
So what are the benefits of using the parental trust model?
- Because this avoids repeated loading, there is no need for the child classloader to load again when the parent has loaded the class.
- Considering the security factors, let's imagine that if we don't use this delegate pattern, we can use a custom string to dynamically replace the defined type in the Java Core API at any time, so there's a very big security risk, and the way that parents delegate, you can avoid this situation, Because the string has already been loaded at startup, the user-defined class is unable to load a custom ClassLoader.
Attached: Android classloader Introduction
Android ClassLoader Parental delegation mode