Classloader for java (2)

Source: Internet
Author: User
This article will introduce Java class loading principles and processes in depth. Although you do not need to understand the class loading process in many cases, if you want to know how Java works, to define your own class loaders, you must understand the class loading process.
You will be involved in the class loading process. Understanding this process will be of great help to you. This article describes the process of class loading through step-by-step analysis. We hope this analysis method will be helpful to you. The JDK used in this article is Sun's jdk_1.4.2 version. Of course, here we will focus on the principle and it has little to do with JDK itself. This article attempts to solve the following problems: class loading principle
Bootstrap loader, extended class loader, and system Class Loader
If you know which class loader is loaded for a class
If the system class loader loads those classes

 

First, we need to analyze the class loading principle. By default, Java has three types of loaders: The bootstrap loader, the extended class loader, and the system class loader (also called the application Class Loader)

 

The bootstrap loader is responsible for loading the system classes in the JDK. This type of loader is implemented in C language and cannot be obtained in Java programs. This is a concept for Java programs, basically, you don't need to consider its existence. classes such as string and integer are loaded by the bootstrap loader. the extension class loader is responsible for loading standard extension classes, which are generally implemented in Java. This is a real Java class loader and is responsible for loading classes in JRE/lib/Ext, like a normal class loader, this class loader is not very important to us. We can obtain this class loader through Java programs. The system class loader loads the loader of the first application class (in fact, this definition is not accurate, as you will see below), that is, the loader of the mainclass is loaded when the Java mainclass is executed, this loader is implemented in Java and widely used. It is responsible for loading the specified class in classpath. There is a certain relationship between classloaders (parent-child relationship). We can think that the parent loader of the extended classloaders is the bootstrap classloaders (of course not so, because the performance of the bootstrap loader
In Java, It is null). However, the parent loader of the system class loader must be an extended Class Loader. The class loader will give the parent loader a chance to load the class, only the parent loader cannot be loaded.
Will be loaded by yourself. We cannot obtain the bootstrap loader because it is implemented in c and the class loaded by the bootstrap loader returns null through the getClassLoader method.
The bootstrap loader cannot be operated directly, but we can determine whether the Class is loaded by the bootstrap loader based on whether the Class. getClassLoader method is null.
The following method gets the path of the class loaded by the bootstrap loader (each jar package or folder corresponds to a URL); sun. misc. launcher. getBootstrapClassPath (). getURLs () You can output the Java code directly in your main function.
  1. System. out. println (java. util. Arrays. asList (sun. misc. Launcher. getBootstrapClassPath (). getURLs (). toString ());
System.out.println(java.util.Arrays.asList(sun.misc.Launcher.getBootstrapClassPath().getURLs()).toString());

 

The result is:

 

In fact, we can specify the class path of the bootstrap loader. java provides a-Xbootclasspath parameter, but this parameter is not a standard parameter. Java-Xbootclasspath: Specifies the loading path (jar file or directory) of the boot Class Loader during runtime. java-Xbootclasspath/p: is the same as above, but put this path in front of the original path java-Xbootclasspath/a: This is to add a class path after the original boot class path. We mentioned above that loading the first application class is not necessarily a system loader. If I put the path of this application class in the bootstrap class path, it will be loaded by the bootstrap loader.
Java-Xbootclasspath/a: myjar. jar MainClass
If MainClass is in myjar. jar, the class will be loaded by the bootstrap loader. If you want to see the details, use the-verbose parameter. To make it clearer, use redirection (in windows ):
Java-verbose-Xbootclasspath/a: myjar. jar MainClass-> C:/out.txt
With this parameter, we can implement our own system class, such as replacing the implementation of java. lang. Object, which can be expanded by ourselves.
Some methods, but it does not seem to be good because it is not a standard. We are most concerned with the system class loader. Generally, we think that the system class loader is the first class loader for loading applications,
That is, java
Although this statement is not rigorous, we can still think of it as basically because we rarely change the loader and the extension.
The default behavior of the class loader. It should be said that the system class loader is responsible for loading classes in the classpath path that are not loaded by the extended Class Loader (of course, the class loader is also loaded ). If
This class exists in classpath, but this class is also extending the class path of the Class Loader, so the system class loader will not be able to load it. We rarely change the behavior of the extended class loader, so the classes you define are generally system class loaders.
It is very easy to get the system class loader. Suppose MyClass is a class you defined.
MyClass. class. getClassLoader () returns the system class loader. Of course, this method cannot be absolutely correct. We can use a simpler and more correct method: Java code
  1. ClassLoader. getSystemClassLoader ();
    // Obtain the system class loader.

Classloader. getsystemclassloader (); // obtain the system class loader.

 

We know that ClassLoader is an abstract class, so the system class loader must be a subclass Implementation of ClassLoader. Let's take a look at what Java code it is.
  1. ClassLoader. getSystemClassLoader (). getClass ();
    // The result is class sun. misc. Lancher $ AppClassLoader.

Classloader. getsystemclassloader (). getclass (); // The result is class sun. Misc. lancher $ appclassloader

 

We can see that this is sun's implementation. From the name, we can see that it is an internal class. At present, I have not seen this source code, and it does not seem very clear:
Let's look at its parent class: Java code
  1. ClassLoader. getSystemClassLoader (). getClass (). getSuperclass ();
ClassLoader.getSystemClassLoader().getClass().getSuperclass(); 

 

The result is: class java.net. URLClassLoader, which is a j2se standard class. Its parent class is SecureClassLoader, while SecureClassLoader inherits ClassLoader. Now the entire relationship should be clear. We can see that almost all ClassLoader implementations inherit URLClassLoader.
Because the system class loader is very important and can be directly controlled, we will introduce it later, but let's take a look at the extended class first.
Loaders and their relationships.
The extension class loader seems to be an inconspicuous role. It is responsible for loading java standard extensions (all jar files under the jre/lib/ext directory). It is actually a common loader, visible and tangible. The first question is, how do I know where the extension class loader is?
There is no direct way to get the extended class loader, but we know that it is the parent loader of the system class loader. We can easily get the system class loader, so we can indirectly obtain the extension class loader:

 

Java code
  1. ClassLoader. getSystemClassLoader (). getParent (). getClass ();
ClassLoader.getSystemClassLoader().getParent().getClass(); 

 

In fact, the extension class loader is indirectly obtained through the system class loader to see what it is: the result is: class sun. misc. launcher $ ExtClassLoader is an internal class like the system class loader and is defined in the same class.
Let's also look at its parent class: Java code
  1. ClassLoader. getSystemClassLoader (). getParent (). getClass (). getSuperclass ();
ClassLoader.getSystemClassLoader().getParent().getClass().getSuperclass(); 

 

The result is also class java.net. URLClassLoader.
The extension class loads all classes under the jre/lib/ext directory, including jar and all classes under the directory (the directory name does not have to be classes ).
Now you can answer the above question. You can write a HelloWorld and put it in a directory under jre/lib/ext /.
For example, jre/lib/ext/myclass/HelloWorld. class
Then, when you set a path to this class in your classpath and execute java HelloWorld in the result, this class is loaded by the extended class loader, which proves the Java code.
  1. Public
     
    Static
     
    Void
    Main (String [] args ){
  2. System. out. println ("loaded"
    + HelloWorld.
    Class
    . GetClassLoader (). getClass ());
  3. System. out. println ("Hello World"
    );
  4. }
public static void main(String[] args){System.out.println("loaded by"+HelloWorld.class.getClassLoader().getClass());System.out.println("Hello World");}

 

The result shows that the class sun. misc. Launcher $ ExtClassLoader can still be run if you delete the myclass directory under jre/lib/ext.
Class sun. misc. lancher $ AppClassLoader if you do not know this process, assume that you have a copy of classpath in your extension class path or a relatively low version, when you use a new version, you will find that
You will not be surprised when you know this process. In addition, two different class loaders can load a class with the same name. That is to say, although the extension class loader loads a class, the system class loader can
Load your own version,
However, this is not the case for existing implementations. The ClassLoader method will request the parent class loader to load first. If you define a class loader, you can modify the default behavior, or even make
He does not have a parent loader.
Here is a way to get the path to the extension class loader: Java code
  1. String path = System. getProperty (
    "Java. ext. dirs"
    );
  2. File dir = new
    File (path );
  3. If
    (! Dir. exists () |! Dir. isDirectory ()){
  4. Return
    Collections. EMPTY_LIST;
  5. }
  6. File [] jars = dir. listFiles ();
  7. URL [] urls = new
    URL [jars. length];
  8. For
    (
    Int
    I =
    0
    ; I <jars. length; I ++ ){
  9. Urls [I] = sun. misc. URLClassPath. pathToURLs (jars [I]. getAbsolutePath () [0
    ];
  10. }
  11. Return
    Arrays. asList (urls );
     String path=System.getProperty("java.ext.dirs");        File dir=new File(path);        if(!dir.exists()||!dir.isDirectory()){            return Collections.EMPTY_LIST;        }        File[] jars=dir.listFiles();        URL[] urls=new URL[jars.length];        for(int i=0;i<jars.length;i++){            urls[i]=sun.misc.URLClassPath.pathToURLs(jars[i].getAbsolutePath())[0];        }        return Arrays.asList(urls);

 

We basically don't care about the extension class loader, and seldom put your own jar in the extension path. In most cases, we don't feel its existence, of course, if you need to put it in this directory, you must know this process. It will take precedence over the class in classpath. Now we should clearly know which loader is loaded for a class and why it is loaded. If we want to obtain the Class Loader for a class at runtime, you can directly use the getClassLoader () method of the Class.
User-Defined classes are generally loaded by the system class loader. We seldom directly use the class loader to load classes, and even seldom load classes by ourselves.
Because classes are automatically loaded during use, when A class is used, the class is automatically loaded. For example, new A () causes Class A to be automatically loaded, but this loading only happens once. You can also use the system class loader to manually load classes. ClassLoader provides the Java code for this interface.
  1. ClassLoader. getSystemClassLoader (). loadClass (
    "ClassFullName"
    );
ClassLoader.getSystemClassLoader().loadClass("classFullName"); 

 

This clearly specifies the use of the system class loader to load the specified class, but if the class can be loaded by the extended class loader, the system class loader will not have a chance. The most common method is to use Class. forName to load the Class used. This method does not specify a specific ClassLoader and uses the ClassLoader of the calling Class.
That is to say, the class loader of the class that calls this method will be used to load this class. For example, if class. forname is used in Class A to load Class B, the class loader that loads Class A will be used to load Class B, so that the class loaders of the two classes are the same. Finally, we will discuss how to obtain the classes loaded by a Class Loader. This seems to have some usage value and we can see which classes are loaded. In fact, this is not very difficult, because one of the classloader's classes member variables is used to save the list of classes loaded by the class loader, and there is a method for Java code
  1. Void
    AddClass (Class c) {classes. addElement (c );}
void addClass(Class c) { classes.addElement(c);} 

 

This method is called by JVM.
We only need to use reflection to obtain the value of classes. However, if classes is declared as private, we need to modify its access permissions (it is easy to do without a security manager). Java code
  1. Classes = ClassLoader.
    Class
    . GetDeclaredField (
    "Classes"
    );
  2. Classes. setAccessible (true
    );
  3. List ret = (List) classes. get (cl); // classes is a Vector

Classes = ClassLoader. class. getDeclaredField ("classes"); classes. setAccessible (true); List ret = (List) classes. get (cl); // classes is a Vector

 

Unfortunately, there is no way for the bootstrap loader to obtain the loaded class, because it is implemented in C and is difficult to control in Java.

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.