The virtual machine design team takes the "fully qualified name of a class to describe the binary byte stream of this class" in the class loading phase and puts it outside the Java virtual machine. So that the application can decide for itself how to get the required class, the code block that implements the action is called the "ClassLoader"
There are 2 classes of ClassLoader in Java, one is provided by the system, the other is written by Java application developers
The system provides a class loader that consists of 3 of the following:
1, Start class loader (Bootstarp ClassLoader)
This classloader is controlled by the JVM itself.
Classes that mainly load the JVM's own work: a class library that can be identified by the virtual machine under the path of the%java_home%\lib path or the-xbootclasspath parameter (identified by the filename only, such as: Rt.jar, the name does not conform to the class library will not be loaded into the virtual machine memory
Startup class loader cannot be referenced directly by Java program
2, Extended class loader (Extension ClassLoader)
The class loader is implemented by the static inner class of the Sun.misc.Launcher class Extclassloader
Responsible for loading the Java.ext.dirs parameter (the default value is%java_home%\jre\lib\ext and can be specified by the VM parameter-djava.ext.dirs) specify all class libraries in the path
Developers can use the Extended class loader directly
3, Application class loader (application ClassLoader)
The class loader is implemented by the static inner class of the Sun.misc.Launcher class Appclassloader
Responsible for loading the Java.class.path parameter (the default value is the value of the system environment variable classpath, which can be specified by the VM parameter-djava.class.path) specify all class libraries in the path
System.out.println (System.getproperty ("Java.class.path"));
When this parameter is printed in eclipse, the result is neither the value of the system environment variable classpath, Nor is the VM parameter-djava.class.path the specified value, because each eclipse project contains a. classpath file that actually outputs the value specified in the file
Developers can use the Application class loader directly
Custom class Loader
In addition to the system-supplied ClassLoader, developers can implement their own classloader by inheriting the Java.lang.ClassLoader class and overriding the class's Findclass method
Package com.test;
Import Java.io.ByteArrayOutputStream;
Import Java.io.File;
Import Java.io.FileInputStream;
Import java.io.IOException; public class Myclassloader extends classloader{@Override public class<?> findclass (String name) throws
undexception {System.out.println ("Use Myclassloader Findclass method."); Name = Com.test.Test//filename = test.class String fileName = name.substring (Name.lastindexof (".")
+1) + ". Class";
byte[] bytes = loadClassData ("c:\\seanapp\\" +filename);
Return defineclass (name, bytes, 0, bytes.length);
Public byte[] loadClassData (String name) {FileInputStream fileInput = null;
Bytearrayoutputstream bytesoutput = null;
try {fileInput = new FileInputStream (new File (name));
Bytesoutput = new Bytearrayoutputstream ();
int b = 0;
while ((b = fileinput.read ())!=-1) {bytesoutput.write (b);
return Bytesoutput.tobytearray ();
catch (Exception e) {e.printstacktrace ();
Finally {try { if (fileInput!= null) fileinput.close ();
catch (IOException e) {e.printstacktrace ();
} return null;
public static void Main (string[] args) {Myclassloader myclassloader = new Myclassloader ();
try {class< extends object> TestClass = Myclassloader.loadclass ("Com.test.Test");
Object obj = testclass.newinstance ();
System.out.println (Obj.getclass (). getClassLoader (). toString ());
catch (Exception e) {e.printstacktrace (); }
}
}
Place the Test.class file generated after the test class is compiled into the c:\seanApp\ path
public class Test {public
test () {}
}
The results of the operation are:
Sun.misc.launcher$appclassloader@761db1c5
is not very strange. is not loaded by the Myclassloader class, to clarify this point, need to understand ClassLoader's superior delegation mechanism (some books are also referred to as the parental delegation mechanism, the name is called because in the subordinate class loader to hold a higher class loader's global variables, And this global variable has a variable named parent)
The boot ClassLoader, which belongs to the class loader used internally by the JVM, has neither a superior class loader nor a subordinate class loader, and therefore does not comply with ClassLoader's superior delegation mechanism and is only a class loading tool for the JVM, so we start with the Extended class loader and the application class loader
An instance of the Extclassloader class is created in the constructor method of the Sun.misc.Launcher class, and an instance of the Appclassloader class is created with that instance
Public Launcher () {
//Create extension class loader
ClassLoader extcl;
try {
extcl = Extclassloader.getextclassloader ();
} catch (IOException e) {
throw new Internalerror ("could Not create extension class loader ");
Create the Application class loader
try {
loader = Appclassloader.getappclassloader (EXTCL) by using the Extended class loader already created;
IOException e) {
throw new Internalerror ("Could not create application class loader");
......
Extended class loader instantiation process
Static Class Extclassloader extends URLClassLoader {public
static Extclassloader Getextclassloader () throws ioexception{
final file[] dirs = Getextdirs ();
......
return new Extclassloader (dirs);
......
}
private static file[] Getextdirs () {
//loading path
String s = System.getproperty ("Java.ext.dirs");
......
}
Public Extclassloader (file[] dirs) throws IOException {
//The second parameter specifies the parent class loader, and here is null
//Description The Extended class loader does not have a superior class
loader Super (Getexturls (dirs), NULL, factory);
This.dirs = dirs;
}
......
}
The instantiation process of the Application class loader, which determines that the ancestor of the Application class loader is the Extended class loader
Static Class Appclassloader extends URLClassLoader {
//EXTCL is an instance of the Extclassloader class public
static ClassLoader Getappclassloader (Final ClassLoader extcl)
throws ioexception{
final String s = System.getproperty (" Java.class.path ");
Final file[] Path = (s = = null)? New File[0]: Getclasspath (s);
......
return new Appclassloader (URLs, EXTCL);
......
}
Appclassloader (url[] URLs, ClassLoader parent) {
//The ancestor of the Application class loader is the extended class loader
super (URLs, parent, factory);
}
......
}
Because the custom class loader needs to be implemented by inheriting the ClassLoader class, the constructor of the ClassLoader class is first invoked in the constructor of the custom ClassLoader to see the constructor of the ClassLoader class
Private ClassLoader parent;
private static ClassLoader SCL;
Protected ClassLoader () {This
(Checkcreateclassloader (), Getsystemclassloader ());
}
Private ClassLoader (Void unused, ClassLoader parent) {
this.parent = parent;
}
The public static ClassLoader Getsystemclassloader () {
//SCL creates
Initsystemclassloader () in the modification method;
..., return
SCL;
}
private static synchronized void Initsystemclassloader () {
if (!sclset) {
if (SCL!= null)
throw new Illega Lstateexception ("recursive invocation");
Gets an instance of the Launcher class
sun.misc.Launcher L = sun.misc.Launcher.getLauncher ();
if (l!= null) {
throwable oops = null;
The SCL is the Application class loader
SCL = L.getclassloader ()
, referring to the constructor of the previous launcher class. ......
Sclset = true;
}
}
The ancestor of the visible custom class loader is the application class loader
If a class loader receives a request for an add-in class, it first does not attempt to load the class itself. Instead, the request is delegated to the parent class loader, which is the case for each class loader, and all loader requests should eventually be routed to the top-level ClassLoader (extended ClassLoader). The subordinate class loader will attempt to load the class itself only when the parent class loader has feedback that it cannot complete the load request (its class loading scope does not find the required class), which is the superior delegation mechanism of the ClassLoader
The virtual machine will call the Loadclassinternal method load class in the ClassLoader class
This are invoked by the virtual machine to load a class.
Private synchronized Class loadclassinternal (String name) throws classnotfoundexception{return LoadClass (name);
Invoking this is equivalent to invoking LoadClass (Name,false).
Public class<?> loadclass (String name) throws ClassNotFoundException {return LoadClass (name, false);}
Subclasses of ClassLoader are encouraged to override Findclass (String),//rather than. Protected synchronized class<?> loadclass (String name, Boolean resolve) throws classnotfoundexception{//
Check if the class has already been loaded class C = Findloadedclass (name);
if (c = = null) {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 into order//to find the class.
c = findclass (name);
} if (resolve) {resolveclass (c);}
return C; }
Through the source code of the LoadClass method, we can see that the class loader first checks whether the class has been loaded, and if it is not loaded, calls the parent class loader to load the class (if the parent class loader is empty, see if the Startup class loader loaded the Class), if the parent class loader fails to load, Call the Findclass method of the lower class loader to load
To ensure that a custom ClassLoader still follows a superior delegation mechanism, JDK recommends implementing a custom class loader by overriding the Findclass method, rather than overriding the LoadClass method (see note 1)
Look at the JDK's description of the Findclass method:
Finds the class with the specified binary name.
This method should is overridden by class loader implementations
which follow the delegation model for loading classes, And'll is invoked by the
loadclass to checking the
parent class loader for the requested class. The default implementation
throws a ClassNotFoundException
The Resolveclass method in the LoadClass method is also curious, incidentally, to see the effect of this method:
Links the specified class. This (misleadingly named) method is
used by a class loader to link a class. If the Class C has
already been linked, then this method simply returns. Otherwise, the
class is linked as described in the "Execution" chapter of the
Java Language specification (http://j ava.sun.com/docs/books/jls/).
You can find that the virtual machine will call this method to complete the connection process of the class, and the connection process of the class is as detailed: http://blog.csdn.net/a19881029/article/details/17068191
Viewing the source code for the ClassLoader class shows that many methods are implemented by invoking the local method (the native modifier-modified method)
The advantage of organizing the relationship between class loaders using the superior delegation mechanism is that the Java class, along with its classloader, has a hierarchical relationship of precedence. For example: Java.lang.Object class, which is stored in Rt.jar, no matter which class loader to load this class, will eventually be entrusted to the boot class loader to load, the startup ClassLoader in its search scope can only search the Java.lang.Object class in Rt.jar (see note 2), which can To ensure that the object class is always loaded by the boot ClassLoader from the java.lang.Object in Rt.jar, ensuring uniqueness of the object class (see note 3)
If you do not use the superior delegation mechanism, loaded by the various class loaders, If the user implements a class named Java.lang.Object and loads it with a custom classloader, there will be several different object classes in the system, and the most basic behavior in the Java type System will not be guaranteed and the application will become cluttered.
Note:
1, why JDK does not recommend implementing custom class loaders by overriding the LoadClass method.
Implementing a custom class loader by overriding the Findclass method: When the LoadClass method load class is invoked, because the custom ClassLoader does not override the LoadClass method, the LoadClass method of the ClassLoader class is actually invoked, This method guarantees that if the upper class loader can load the required classes, the loading action is delegated to the superior class loader, and when the upper class loader cannot complete the loading action, the loading action is completed by the Findclass method of the subordinate class loader, which conforms to the class loader superior delegation mechanism.
Implementing a custom class loader by overriding the LoadClass method: When the LoadClass method is called to load a class, the LoadClass method overridden in the custom class loader is called directly to complete the load action. If the overridden LoadClass method does not implement the process of first attempting to delegate the load action to the parent class loader, it will destroy the superior delegation mechanism, which can be broken, but requires a better reason (Jdbc,jndi to break the superior delegation mechanism)
Of course, if in the rewritten LoadClass method first tries to let the superior class loader complete the loading process, then essentially is no no problem, just still awkward, the first is why not use ready-made implementation. Second, if the Superior class loader cannot complete the load action, or the Findclass method to delegate the loading process to the custom ClassLoader, the key problem is that in the ClassLoader class, Findclass is an empty method, That means you still have to rewrite your Findclass method, go around a big circle, and come back, unless you can make sure that the parent class loader can complete the load action, you will not invoke the Findclass method of the custom ClassLoader, but why do you implement your own ClassLoader. So it's right to implement a custom ClassLoader by overriding the Findclass method, but still try it. Implement a custom class loader by overriding the LoadClass method:
2, in the custom class loader, use the DefineClass method to load a java.lang.Object class of my own implementation
Package Java.lang;
Public class Object {public
object () {}
}
The runtime throws the following exception (the blocked package name):
java.lang.SecurityException:Prohibited Package Name:java.lang
In fact, loading all the "java." The first class throws the exception, which should be protected by the underlying class that the JDK implements for itself
......
if ((name!= null) && name.startswith ("java.") {
throw new SecurityException ("Prohibited Package Name:" +
name.substring (0, Name.lastindexof ('. '));
}
......
3, compare 2 classes are equal, only if these two classes are loaded by the same class loader is meaningful, otherwise, even if these 2 classes are derived from the same class file, as long as the loading of their class loader is different, these 2 classes must be unequal