Original address: http://www.ibm.com/developerworks/cn/java/j-lo-classloader/index.html
The ClassLoader (class loader) is a very important concept in java™. The ClassLoader is responsible for loading the Java class's byte code into the Java virtual machine. In this paper, the basic concepts of Java ClassLoader are introduced in detail, including the proxy mode, the concrete process of loading class and the thread context class loader, and then how to develop their own classloader, and finally introduce the application of ClassLoader in Web container and osgi™.
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
wait for 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.
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 way: Java source programs (. java files) are converted to Java bytecode (. class files) after being compiled by the Java compiler. The ClassLoader is responsible for reading the Java byte code and converting it into java.lang.Class
an instance of the class. Each such instance is used to represent a Java class. newInstance()
an object of the class can be created by means 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.
Basically all ClassLoader are java.lang.ClassLoader
an instance of the class. This Java class is described in detail below.
java.lang.ClassLoader
Class Introduction
java.lang.ClassLoader
The basic function of a class is to find or generate its corresponding byte code based on the name of a specified class, and then define a Java class from those byte codes, which is java.lang.Class
an instance of the class. In addition, it ClassLoader
is also responsible for loading the resources required for Java applications, such as files and configuration files. However, this article only discusses the functionality of its load class. In order to complete this function of the load class, a ClassLoader
series of methods are provided, and the more important methods are shown in table 1. The details of these methods are described below.
Table 1. Methods related to load classes in ClassLoader
Method |
Description |
getParent () |
Returns the class loader's parent class loader. |
loadclass (String name) |
loads the class with the name name , and returns the result java.lang.c Lass an instance of the class. |
findclass (String name) |
Find the class with the name name , and the result is java.lang.c Lass an instance of the class. |
findloadedclass (String name) |
finds the already loaded class with the name name and returns the result java.lang.class an instance of the class. |
defineclass (String name, byte[] B, int off, int len) |
put byte array b is converted to a Java class, and the result returned is an instance of the Java.lang.Class class. This method is declared as final . |
resolveclass (class<?> c) |
link to the specified Java class. |
For the method given in table 1, the value of the parameter representing the class name is the binary name
name of the class. It is important to note that the representation of the inner class, such as com.example.Sample$1
and com.example.Sample$Inner
other representations. These methods are described below for further instructions on how the ClassLoader works. The tree-like structure of the ClassLoader is described below.
The tree-like structure of the ClassLoader
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 class loader): It is used to load Java's core library, which is implemented by native code and does not inherit from
java.lang.ClassLoader
.
- Extension class loader (Extensions class loader): 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 class Loader: It loads Java classes according to the Classpath (CLASSPATH) of the Java application. In general, Java-applied classes are loaded by it. You can
ClassLoader.getSystemClassLoader()
get it by.
In addition to the system-provided ClassLoader, developers can java.lang.ClassLoader
implement their own ClassLoader by inheriting classes to meet some special requirements.
All Class loaders have a parent class loader, in addition to the boot class loader. It can be obtained by the method given in table 1 getParent()
. For the system-provided ClassLoader, the parent classloader of the system ClassLoader is the extension class loader, and the parent classloader of the extension ClassLoader is the boot class loader, and for a developer-written class loader, its parent classloader is the ClassLoader that loads the class loader Java class. Because the ClassLoader Java class is like any other Java class, it is also loaded by the ClassLoader. In general, the developer-written class loader's parent ClassLoader is the System class loader. The ClassLoader is organized in such a way that it forms a tree-like structure. The root node of the tree is the boot class loader. A typical class loader tree structure is shown in Figure 1, where the arrows point to the parent ClassLoader.
Figure 1. Class Loader tree-like organizational structure
Listing 1 shows the tree-like structure of the ClassLoader.
Listing 1. A tree-like structure showing the ClassLoader
public class Classloadertree {public static void Main (string[] args) { ClassLoader loader = Classloadertree.clas S.getclassloader (); while (loader! = null) { System.out.println (loader.tostring ()); Loader = Loader.getparent ();}} }
Each Java class maintains a reference to the ClassLoader that defines it, and getClassLoader()
this reference can be obtained by means of a method. The full parent ClassLoader is output in code Listing 1 by means getParent()
of a recursive call method. Code Listing 1 runs as shown in Listing 2.
Listing 2. Demonstrates the results of a tree-like organizational structure of the ClassLoader
[Email protected] [Email protected]
As shown in Listing 2, the first output is the class ClassLoaderTree
loader, the System class loader. It is an sun.misc.Launcher$AppClassLoader
instance of the class, and the second output is an extension class loader, which is an sun.misc.Launcher$ExtClassLoader
instance of a class. It is important to note that there is no output boot class loader, because some JDK implementations are returned to the parent class loader as the Boot class loader getParent()
null
.
After understanding the tree-like structure of the ClassLoader, the following describes the proxy mode of the ClassLoader.
Agent mode for Class loader
When the ClassLoader tries to find the byte code of a class and define it itself, it proxies it to its parent class loader, and the parent class loader tries to load the class first, and so on. Before introducing the motives behind the proxy pattern, it is first necessary to explain how the Java virtual machine determines that two Java classes are the same. The Java virtual machine depends not only on whether the full name of the class is the same, but also on whether the class loader loading this class is the same. The two classes are the same only if they are the same. Even the same byte code is different from the classes that are obtained after the loading of different classloader. A Java class, for example com.example.Sample
, generates a byte code file after compilation Sample.class
. Two different ClassLoader ClassLoaderA
and ClassLoaderB
read the Sample.class
file separately, and define an java.lang.Class
instance of two classes to represent the class. These two instances are not the same. For Java virtual machines, they are different classes. Attempting to assign values to objects of these two classes throws a run-time exception ClassCastException
. The following is an example of how to specify. The Java class is given in code Listing 3 com.example.Sample
.
Listing 3. Com.example.Sample class
Package com.example; public class Sample { private sample instance; public void Setsample (Object instance) { this.instance = (Sample) instance; } }
As shown in Listing 3, the com.example.Sample
method of the class setSample
takes a parameter of a java.lang.Object
type and casts the argument to a com.example.Sample
type. The code to test whether the Java class is the same is shown in Listing 4.
Listing 4. Test if the Java class is the same
public void Testclassidentity () { String Classdatarootpath = "C:\\workspace\\classloader\\classdata"; Filesystemclassloader FSCL1 = new Filesystemclassloader (classdatarootpath); Filesystemclassloader Fscl2 = new Filesystemclassloader (classdatarootpath); String className = "Com.example.Sample"; try { class<?> class1 = Fscl1.loadclass (className); Object obj1 = Class1.newinstance (); class<?> Class2 = Fscl2.loadclass (className); Object obj2 = Class2.newinstance (); Method Setsamplemethod = Class1.getmethod ("Setsample", java.lang.Object.class); Setsamplemethod.invoke (Obj1, obj2); } catch (Exception e) { e.printstacktrace (); } }
The Code Listing 4 uses FileSystemClassLoader
two different instances of the class to load the class separately, com.example.Sample
obtains two different java.lang.Class
instances, newInstance()
and then generates two classes of objects by means of the method obj1
obj2
, and finally calls the object via the Java reflection API obj1
. Method setSample
that attempts to obj2
assign an object to obj1
an internal instance
object. Code Listing 4 runs as shown in Listing 5.
Listing 5. Test the Java class for the same run result
Java.lang.reflect.InvocationTargetException at Sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Method) at Sun.reflect.NativeMethodAccessorImpl.invoke (nativemethodaccessorimpl.java:39) at Sun.reflect.DelegatingMethodAccessorImpl.invoke (DELEGATINGMETHODACCESSORIMPL.JAVA:25) at Java.lang.reflect.Method.invoke (method.java:597) at ClassLoader. Classidentity.testclassidentity (classidentity.java:26) at ClassLoader. Classidentity.main (classidentity.java:9) caused by:java.lang.ClassCastException:com.example.Sample cannot be cast to Com.example.Sample at Com.example.Sample.setSample (sample.java:7) ... 6 more
As you can see from the running results shown in Listing 5, the runtime throws an java.lang.ClassCastException
exception. Although the names of the two objects are the obj1
obj2
same as the classes, the two classes are loaded by different class loader instances and are not considered to be identical by the Java virtual machine.
Knowing this, you can understand the design motivation of the proxy pattern. The proxy mode is designed to ensure the type safety of the Java Core library. All Java applications require at least a reference java.lang.Object
class, which means that the java.lang.Object
class needs to be loaded into the Java Virtual machine at runtime. If this loading process is done by the Java application's own classloader, it is likely that there are multiple versions of the java.lang.Object
classes, and that the classes are incompatible. Through the proxy mode, the loading of the classes of the Java Core Library is accomplished by the bootstrap ClassLoader, which ensures that Java applications are all compatible with the same version of the Java Core Library.
Different Class loaders create additional namespaces for classes of the same name. Classes of the same name can and exist in the Java virtual machine, and only need to load them with a different class loader. Classes loaded by different classloader are incompatible, which is equivalent to creating a separate Java class space within the Java virtual machine. This technique is used in many frameworks and is described in more detail later.
"Not finished copying"
Full pdf download (private collection): Http://pan.baidu.com/s/1kT5NSaV Password: g20z
Delve into Java ClassLoader [go]