In-depth understanding of the JVM (6)-Class loader

Source: Internet
Author: User
Tags inheritance

The virtual machine design team takes the "fully qualified name of a class to obtain a binary byte stream (that is, bytecode) that describes this class" in the class-loading phase, which is implemented outside the Java virtual machine, so that the application can decide for itself how to get the required class. The code module that implements this action is called the class loader.

In general, Java virtual machines use Java classes in the following way: Java source programs (. java files) are converted to bytecode (. class files) after being compiled by the Java compiler. The ClassLoader is responsible for reading the Java byte code and converting it into 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. More detailed information can be found in the previous article in the class loading process described in the loading phase of a few examples (jar package, Applet, dynamic agent, JSP, etc.). class and Class loader

Although the ClassLoader is only used to implement the load action of a class, its role in Java programs is far greater than the class loading phase. For any class, it is necessary to establish its uniqueness in the Java Virtual machine, together with the class loader that loads it, and the class itself, each with a separate class namespace. In layman's terms: Compare whether two classes are "equal" (the "equality" referred to here, including the Equals () method of the Class object, the IsAssignableFrom () method, the Isinstance () method, and the return result of the (), including the use of instanceof () Keywords to do object ownership relationship decision, etc.), only in these two classes by the same class loader loaded by the premise of meaning, otherwise, even if the two classes from the same class file, is loaded by the same virtual machine, as long as loading their class loader is different, then the two classes must be unequal. Parental delegation Model

From the JVM's point of view, there are only two different classloader: the launcher ClassLoader (Bootstrap ClassLoader), which is implemented by C + +, is a part of the virtual machine itself; all other class loaders, these classes are implemented by Java, independent of the virtual machine outside, And all inherit from the abstract class Java.lang.ClassLoader.

From the JAVA developer's point of view, the ClassLoader can be more granular: Start the ClassLoader (Bootstrap ClassLoader) Such loaders are responsible for storing in the <java_home>\lib directory, or are- The Xbootclasspath parameter is specified in the path and is recognized by the virtual machine (recognized by the file name only, such as Rt.jar, the class library whose name does not match even if it is placed in the Lib directory will not be loaded) The class library is loaded into the virtual machine memory. The startup ClassLoader cannot be referenced directly by a Java program, and when a user writes a custom class loader, it is necessary to delegate the load request to the boot class loader directly using NULL instead. Extension class loader (Extension ClassLoader) This classloader is implemented by Extclassloader (Sun.misc.launcher$extclassloader). It is responsible for loading <java_home>/lib/ext or all class libraries in the path specified by the JAVA.EXT.DIR system variable into memory, and developers can use the extension class loader directly. The class loader for the application ClassLoader (application ClassLoader) is implemented by Appclassloader (Sun.misc.launcher$appclassloader). Because this classloader is the return value of the Getsystemclassloader () method in ClassLoader, it is generally referred to as the System class loader. It is responsible for loading the class library specified on the user classpath (ClassPath), which the developer can use directly, if the application does not have its own classloader, typically this is the default class loader in the program.

Applications developed by developers are loaded with each other by these three kinds of loaders, and, if necessary, can be added to their own defined class loaders. These classloader relationships are typically shown in the following figure:

The above diagram shows a hierarchical relationship between the ClassLoader, called the class loader's parent delegation model (parents delegation models). The model requires that in addition to the top-level startup ClassLoader, the rest of the ClassLoader should have their own parent ClassLoader, where the parent-child relationship between ClassLoader is typically implemented by a combination (composition) relationship rather than through inheritance (inheritance).

Work process

If a class loader receives a request for a class load, it first does not attempt to load itself, but instead delegates the request to the parent ClassLoader, which is the same for each level of loader, recursively, so all load requests should eventually be routed to the top-level startup ClassLoader. The child loader tries to load itself only when the parent loader has feedback that it cannot complete the load request (it does not find the desired class in the search scope).

Advantages

Use the parental delegation model to organize the relationship between ClassLoader, so that the Java class has a hierarchical relationship with precedence as its classloader. For example, the class Java.lang.Object, which is stored in the Rt.jar, regardless of which classloader to load the class, ultimately delegating to the top of the model startup ClassLoader to load, so the Object class in the program's various class loader environment is the same class.

Conversely, if a parent does not delegate the model and is loaded by the various ClassLoader, if the user writes a class called ' Java.lang.Object, and puts it in the program's classpath, there will be a number of different object classes in the system, and the program will become chaotic. If a developer tries to write a Java class that has the same name as an existing class in the Rt.jar class library, it will find that it compiles correctly, but it can never be loaded and run.

The parent delegation model is implemented as follows:

Protected synchronized class<?> loadclass (String Name,boolean Resolve) throws classnotfoundexception{
    // Check the class has been loaded or not
    class C = findloadedclass (name);
    if (c = = null) {
        try{
            if (parent! = null) {
                c = parent.loadclass (Name,false);
            } else{
                C = findbootstrapclassornull (name);
            }
        } catch (ClassNotFoundException e) {
            //if throws the exception, the father can not complete the load
        }
        if (c = = NULL) {
            c = findclass (name);
        }
    }
    if (resolve) {
        resolveclass (c);
    }
    return c;
}
destroying parental delegation models thread Context class loader

The

Parental delegation model does not solve all the problems with the ClassLoader that you will encounter in Java application development. Java provides a number of service provider interfaces (services Provider INTERFACE,SPI) that allow third parties to provide implementations for these interfaces. The common SPI has &NBSP;JDBC, JCE, JNDI, JAXP, and jbi . These &NBSP;SPI interfaces are provided by the Java Core library, such as the JAXP SPI interface definition contained in the  javax.xml.parsers package. The implementation code for these SPI is likely to be included in the  jar package that is dependent on the Java application, which can be found through the classpath (ClassPath), such as the jar packages contained in Apache Xerces, which implements the JAXP SPI. The code in the SPI interface often needs to load specific implementation classes. The  newinstance ()   method in the  javax.xml.parsers.documentbuilderfactory class in JAXP is used to generate a new   An instance of documentbuilderfactory . The real class of instances here is inherited from  javax.xml.parsers.documentbuilderfactory, provided by the implementation of the SPI. As in Apache Xerces, the implemented class is Org.apache.xerces.jaxp.DocumentBuilderFactoryImpl. The problem is that the SPI interface is part of the Java Core library and is loaded by the bootstrap ClassLoader, and the Java classes implemented by the SPI are typically loaded by the system ClassLoader. The boot ClassLoader is unable to find the SPI implementation class because it only loads the Java core library. It is also not delegated to the system ClassLoader because it is the ancestor class loader of the system ClassLoader. That is, the class loader's parental delegation model does not solve this problem.

To solve this problem, the Java design team had to introduce a less elegant design: The Thread Context class loader (ClassLoader). The thread context ClassLoader was introduced starting with JDK 1.2. The methods in class Java.lang.Thread Getcontextclassloader () and Setcontextclassloader (ClassLoader cl) are used to get and set the context class loader for the thread. If it is not set by the Setcontextclassloader (ClassLoader cl) method, the thread inherits the context class loader of its parent thread. The context class loader for the initial thread that the Java application runs is the application class loader. Code that runs in a thread can load classes and resources through such loaders.

With the thread context ClassLoader, you can do something "corrupt", and the Jndi service uses this thread-context ClassLoader to load the required SPI code, which is the parent ClassLoader requesting the subclass loader to complete the class loader's actions. This behavior is actually through the parent delegation model hierarchy to reverse the use of the ClassLoader, has violated the parent delegation model general principles. Pursuit of procedural dynamics

The term "dynamic" here refers to some of the most popular nouns: Code hot Swap (HOTSWAP), Module thermal deployment (Hot Deployment), and so on. That is, you want the application to be like a computer peripherals, connect the mouse, keyboard, without restarting can immediately use, the mouse out of the problem or need to upgrade the mouse, without downtime or restart.

The current industry "de facto" Java modularity Standard is OSGi, and the key to OSGi's code-hot deployment is the implementation of its custom class-onboard device. The details of OSGi will be explained in detail in a later case study. Custom class Loaders

Api

There are three more important methods.

Method Description
DefineClass (String name, byte[] B, int off, int len) Converts the contents of byte array B into a Java class, which can be considered a file consisting of binary stream bytes, and the returned result is an instance of the Java.lang.Class class. This method is declared final.
LoadClass (String name) Above, the source code has been posted, the implementation of the parent delegation model, call Findclass () to perform the class load action, the return is an instance of the Java.lang.Class class.
Findclass (String name) By passing in the class fully qualified name name to get the corresponding class, returned is an instance of the Java.lang.Class class, the class does not provide a specific implementation, the developer will need to reuse this method when customizing the ClassLoader, when implementing this method calls DefineClass (String name, Byte[] B, int off, int len) method.

Having learned the above, it is easy to realize that the custom ClassLoader has the following two ways: The parent delegation Model: Inheriting the ClassLoader class, simply overriding its Findclass (string name) method without rewriting the LoadClass (string Name) method. Destroying the parental delegation model: Inheriting the ClassLoader class requires the entire override to implement the LoadClass (String name) method of the parent delegation model logic. Example

Let's implement a custom ClassLoader to load the Java byte code stored on the file system.

public class Filesystemclassloader extends ClassLoader {private String rootdir; 
   Public Filesystemclassloader (String rootdir) {this.rootdir = RootDir; } @Override protected class<?> findclass (String name) throws ClassNotFoundException {byte[] classd 
       ATA = getclassdata (name); 
       if (Classdata = = null) {throw new ClassNotFoundException (); 
       } else {return defineclass (name, Classdata, 0, classdata.length); 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.