Reprint: http://www.cnblogs.com/xwdreamer/archive/2011/12/01/2296919.html
1. Introduction to Class Loaders
The ClassLoader is an innovation in the Java language and one of the most important reasons for the popularity of the Java language. It enables Java classes to be dynamically loaded into a Java virtual machine and executed. The ClassLoader emerged from JDK 1.0 and was originally developed to meet the needs of Java applets. Java applets need to download Java class files from the remote to the browser and execute them. Class loaders are now widely used in Web containers and OSGi. In General, Java application developers do not need to interact directly with the same loader. The default behavior of the Java virtual machine is sufficient to meet the needs of most situations. However, if you encounter the need to interact with the ClassLoader, and the mechanism of the ClassLoader is not very well understood, it is easy to spend a lot of time to debug ClassNotFoundException and Noclassdeffounderror and other exceptions. This article will give you a detailed introduction to the Java ClassLoader to help readers understand this important concept in the Java language. Here is a first introduction to some of the underlying concepts.
2. Class Loader Basic Concepts
As the name implies, the ClassLoader (class loader) is used to load Java classes into a Java virtual machine. In general, Java virtual machines use Java classes in the following ways:
- The Java source program (. java file) is converted to a Java byte code (. class file) after it has been compiled by the Java compiler.
- The ClassLoader is responsible for reading the Java byte code (. class file) and converting it to an instance of the Java.lang.Class class. Each such instance is used to represent a Java class.
- An object of the class can be created by using the Newinstance () method of this instance.
- The actual situation can be more complex, such as the Java byte code may be generated dynamically through the tool, or it may be downloaded over the network.
The ClassLoader in Java can be broadly divided into two categories, one for the system, the other for Java application developers. There are three main types of ClassLoader available in the system:
- Boot class loader (Bootstrap ClassLoader): It is used to load Java's core library, which is implemented in native code (c + +) and does not inherit from Java.lang.ClassLoader.
- Extension class loader (Extclassloader): It is used to load the Java extension library. The implementation of the Java virtual machine provides an extension library directory. The ClassLoader finds and loads the Java class in this directory.
- System ClassLoader (App ClassLoader): It loads Java classes based on the Classpath (CLASSPATH) of the Java application. In general, Java-applied classes are loaded by it. It can be obtained by Classloader.getsystemclassloader ().
The ClassLoader is also a Java class, because the class loader of other Java classes is also loaded by the ClassLoader itself, and it is obvious that the first ClassLoader is not a Java class, and this is bootstrap. Bootstrap It is nested within the Java Virtual Machine kernel, the JVM starts, and the class starts, and it is written in the C + + language. all ClassLoader in a Java Virtual machine are organized in a tree structure with a parent-child relationship, and when each ClassLoader object is instantiated, it is necessary to specify a parent ClassLoader object for it or by default the System class loader (App ClassLoader) Loaded for its parent class.
Figure 1: Class loader tree-like organizational structure
Example 1: Test the ClassLoader of the JVM you are using
/*loadersample1.java*/
Public class LoaderSample1 {
Public static void Main (string[] args) {
Class C;
ClassLoader cl;
cl = Classloader.getsystemclassloader ();//System class loader instantiation
System.out.println (CL);//[email protected]
System.out.println ("-----------------");
While (CL! = null) {
cl = cl.getparent ();//Parent Instantiation
System.out.println (CL);//[email protected] and null
}
System.out.println ("-----------------");
try {
C = class.forname ("Java.lang.Object");
cl = C.getclassloader ();//Gets the class loader of the core class Java.lang.Object
System.out.println (C.getname () + ": Classloader is" + cl);
C = class.forname ("LoaderSample1");
cl = C.getclassloader ();//Gets the class loader of the user class LoaderSample1
System.out.println (C.getname () + ": Loader is" + cl);
} catch (Exception e) {
e.printstacktrace ();
}
}
}
Output Result:
1 [email protected]
2-----------------
3 [email protected]
4 NULL
5-----------------
6 Java.lang.Object:Classloader is null
7 Loadersample1:loader is [email protected]
Description:
Line 1th indicates that the System class loader is instantiated from class Sun.misc.launcher$appclassloader
Line 3rd indicates that the parent of the System class loader is instantiated from class Sun.misc.launcher$extclassloader
Line 4th indicates that the parent of the System class loader parent is bootstrap
The 6th line indicates that the core class Java.lang.Object is loaded by bootstrap
Line 7th indicates that the user class LoaderSample1 is loaded by the System class loader
The null representation here is the Bootstrap class loader. This will be explained in the third section.
3. In-depth analysis
In Java each class is loaded by an entity of a classloader, so in the class class, there is a field record of the entity that loads its classloader (when null, it actually refers to Bootstrap ClassLoader). In the Java ClassLoader, in addition to the Boot class loader (both bootstrap ClassLoader), all ClassLoader have a parent classloader (because they themselves are Java classes). the load mechanism of a class follows a delegate pattern: when the ClassLoader has the need to load a class, it requests its parent to load (recursively), and if it is not successfully loaded in its parent loader tree, it is loaded by the current class loader.
The class loader for Java is divided into the following types:
- Bootstrap Classloader:bootstrap ClassLoader is implemented in C + +, and everything starts with the final parent loader for all class loaders. is responsible for loading some key Java classes, such as Java.lang.Object and some other run-time code, into memory first.
- Extclassloader:extclassloader is implemented in Java, is the inner class of Launcher.java, the compiled name is: Launcher$extclassloader.class. This class is loaded by Bootstrap ClassLoader, but because Bootstrap ClassLoader is out of the Java System (c + +), the parent of Launcher$extclassloader.class is set to NULL, which is used to load the class in the Java Run Environment Expansion pack (Jre/lib/ext), and once the path to its loading is established, it will no longer change.
- Appclassloader:appclassloader is implemented in Java and is also the inner class of Launcher.java, the compiled name is: Launcher$appclassloader.class. Appclassloader is when bootstrap ClassLoader loaded Extclassloader, and then bootstrap ClassLoader loaded. So both Extclassloader and Appclassloader are loaded by bootstrap ClassLoader, but the Appclassloader parent is set to Extclassloader. It is not necessarily appropriate for the parent and which classloader to load. This class loader is often used by us and can be called Classloader.getsystemclassloader () to get ( using this method in instance 1 ), If the program does not use a class loader-related operation setting or customizing a new class loader, then all of the Java classes we write will be loaded by it. And its lookup area is what we often say about the classpath, once the loading path is established no longer changes.
- ClassLoader: Generally our custom ClassLoader inherit from the ClassLoader class. For example: URLClassLoader is a subclass of ClassLoader, and URLClassLoader is also the parent of Extclassloader and Appclassloader (note that it is not a parent loader).
3.1. The parent-child relationship between class loaders is:
BootStrap, Extclassloader, Appclassloader (commonly referred to as System ClassLoader)
3.2. The scope of jurisdiction is:
BootStrap------>jre/lib/rt.jar
Extclassloader---------->jre/lib/ext/*.jar
Appclassloader----------All jars or directories specified by the >classpath.
3.3. Delegate mechanism of class loader
When the Java virtual machines load a class, exactly which classloader to load?
- First, the class loader of the current thread to load the first class in the thread.
- If Class A refers to a class B,java the virtual machine will load Class B using the class loader that loads Class A.
- You can also call the Classloader.loadclass () method directly to specify a class loader to load a class.
Each class loader loads a class and then delegates it to its parent class loader. When all ancestor class loaders are not loaded into the class, go back to the initiator ClassLoader and still not load, then throw classnotfoundexception, not to find the son of the initiator ClassLoader. Because there is no getchlid method, even if there is, then when there are more than one son, which one to find?
3.4. When you need to write your own class loader:
- The custom class loader must inherit ClassLoader.
- Override the LoadClass method with the Findclass method. The loadclass of the parent class is called first in LoadClass, and then Findclass is called, typically only findclass is overwritten.
- Override the DefineClass method.
- Note: A custom ClassLoader is often used to decrypt an encrypted class byte code that is written by itself, or it cannot be loaded properly by the system's class loader, even if someone else owns the class file.
Reference: http://blog.csdn.net/lovingprince/article/details/4239491
4.parent Delegation Model
Starting with version 1.2, Java has introduced a parental delegation model to better ensure the security of the Java platform. Under this model, when a loader is requested to load a class, it first delegates its own parent to load, and if the parent can mount it, it returns the class object corresponding to it, and if the parent cannot mount it, it is loaded by the requestor of the parent.
As shown in Figure 2, the parent of Loader2 is the Loader1,loader1 parent for System class loader. Assuming that loader2 is required to load class MyClass, under the parent delegation model, LOADER2 first requests Loader1 to load, Loader1 then requests the System class loader to load MyClass. if the system loader is able to load successfully, the reference of the class object corresponding to the MyClass is returned to Loader1,loader1 and the reference is returned to Loader2, which successfully loads the classes MyClass into the virtual machine. If the System class loader cannot load Myclass,loader1 will attempt to load MyClass, and if Loader1 cannot load successfully, LOADER2 will attempt to mount. If all the parent and loader2 itself cannot be loaded, the load fails.
If there is a successful load, the actual loaded class loader is called the definition class loader, all loaders that can successfully return the class object (including the definition class loader) are called the initial class loaders. as shown in 1, assuming that Loader1 actually loaded MyClass, then Loader1 is the MyClass definition class loader , Loader2 and Loader1 as the initial class loader for MyClass.
Figure 2 The parent delegation model
It should be noted that class loader is an object whose parent-child relationship has no relation to the parent-child relationship of the class. A pair of parent-child loader may be instantiated from the same class, or not, even if the parent loader is instantiated from the child class, and the child loader is instantiated from the parent class. assuming Myclassloader inherits from Parentclassloader, we can have the following parent-child loader:
ClassLoader loader1 = new Myclassloader ();//Parent loader instantiate from subclass, Myclassloader is a subclass of Parentclassloader
Parameter Loader1 to Parent
So why is the parent delegation model more secure? because under this model the user-defined class loader cannot load reliable classes that should be loaded by the father loader, thereby preventing unreliable or even malicious code from replacing the reliable code loaded by the Father loader. in fact, the writer of the class loader is free to choose not to delegate the request to the parent, but as mentioned above, it poses a security problem.
5. Namespaces and their role
Each class loader has its own namespace, and the namespace consists of all classes that use this loader as the initiator class loader. The two classes of different namespaces are not visible, but as long as you get the reference of the class object corresponding to the classes, you can also access the classes of the other namespace. Example 2 demonstrates how a class of a namespace uses a class of another namespace. In the example, LoaderSample2 is loaded by the System class loader, LoaderSample3 is loaded by a custom loader loader, two classes are not in the same namespace, But LoaderSample2 gets the reference of the class object corresponding to LoaderSample3, so it can access the public members of the LOADERSAMPL3 (such as age).
Example 2 access to classes of different namespaces (code not validated)(1) Create Java project:
URLClassLoaderTest1, create Loadersample3.java in this project. Then package the
urlclassloadertest1/loadersample3.class file into a jar package:
Jarloadersample3.jar. and place the jar package in the D-packing directory.
Package uRLClassLoaderTest1;
/*sub/loadersample3.java*/
public class LoaderSample3 {
public int age = 30;
Static code blocks, which are automatically run when the class is loaded.
static {
System.out.println ("LoaderSample3 Loaded");
System.out.println (LoaderSample3.class.getClassLoader ());//type of output class loader
}
}
(2) Create Java project:
URLClassLoaderTest0, creating Loadersample2.java.
Package uRLClassLoaderTest0;
/*loadersample2.java*/
import java.net.*;
import java.lang.reflect.*;
Public class LoaderSample2 {
Public static void Main (string[] args) {
try {
//string Path = System.getproperty ("User.dir");
url[] US = {new URL ("File:d:/jarloadersample3.jar")};
ClassLoader loader = new URLClassLoader (US);
Class C = Loader.loadclass ("Urlclassloadertest1.loadersample3");
System.out.println (LoaderSample2.class.getClassLoader ());//type of output class loader
Object o = c.newinstance ();
Field f = C.getfield ("Age");
int age = F.getint (o);
System.out.println ("Age was" + age);
} catch (Exception e) {
e.printstacktrace ();
}
}
}
Operation Result:
[Email protected]
LoaderSample3 Loaded
[Email protected]
Age is 30
As you can see from the running results, you can create objects in class LoaderSample3 in another namespace and have access to their public member age in LoaderSample2. Also LoaderSample2 is loaded by the System class loader Appclassloader, while LoaderSample3 is loaded by the URLClassLoader.
6. Run-time packages (Runtime package)
Classes belonging to the same package as defined by the same class loader make up the run-time package, deciding whether the two classes belong to the same run-time package, not only to see if their package names are the same, but also to see if the class loader is the same. Only classes that belong to the same run-time package can access the classes and members that the package is visible to each other. Such restrictions prevent the user's own code from impersonating the core class library class to access the Core class library package visible members. Suppose that the user has defined a class java.lang.Yes himself and loaded it with a user-defined class loader, because the Java.lang.Yes and core class libraries java.lang.* loaded by different loaders, they belong to different run-time packages, So java.lang.Yes cannot access the members of the class's package visible in the core class library Java.lang.
7. Summary
After a brief discussion of the class loader, the parent delegation model, the namespace, and the runtime package, I believe we have a certain understanding of their role. namespaces do not completely prohibit the mutual access of classes belonging to different spaces, and the parental delegation model reinforces the security of Java, and the runtime package increases the protection of the package visible members.
Class Loaders Understand