Java class loading/classloader

Source: Internet
Author: User

(1) Types of ClassLoader in the JVM

The JVM has predefined three types of ClassLoader, and when a JVM starts, Java defaults to using the following three types of class loaders:

Bootstrap class loader: The boot ClassLoader is a class loader implemented with native code that is responsible for loading the class library below <java_runtime_home>/lib into memory. Because the boot ClassLoader involves the virtual machine local implementation details, the developer cannot directly get a reference to the startup ClassLoader, so it is not allowed to operate directly from the reference.

Extension class loader: The extension ClassLoader is implemented by Sun's Extclassloader (Sun.misc.launcher$extclassloader). It is responsible for loading the < Java_runtime_home >/lib/ext or the class library in the specified location java.ext.dir the system variable into memory. Developers can use the standard extension class loader directly.

System class Loader: The systems ClassLoader is implemented by Sun's Appclassloader (Sun.misc.launcher$appclassloader). It is responsible for loading the class library specified in the System class path (CLASSPATH) into memory. Developers can use the System class loader directly. It can be obtained by Classloader.getsystemclassloader ().



Extclassloader and Appclassloader are inherited from URLClassLoader.

(2) Rules for class loading

There are two types of class load rules:
1 Parental delegation
2 Class A refers to Class B, then the Class A loader loads class B, guaranteeing that the referenced class is loaded by the same loader

The JVM defaults to the parent delegation mechanism when loading the class. In layman's words, when a particular class loader receives a request to load a class, it first delegates the load task to the parent class loader, recursively, and returns if the parent ClassLoader can complete the class load task, only to load itself when the parent ClassLoader cannot complete the load task.

ClassLoader exists in the parent/child hierarchy at run time, each ClassLoader instance has a reference to its parent ClassLoader, and the parent ClassLoader does not hold a reference to the child ClassLoader, thus forming a unidirectional chain. When a class mount request is committed to a classloader, the default class loading process is as follows:
1. Check that the class has not been loaded, and if it has already been loaded, return
2. Call the parent ClassLoader to load the class if the load returns successfully.
3. Calls its own load class method and returns if the load succeeds
4. If the check is not successful, throw classnotfoundexception.
Simply put, when a classloader on a classloader chain receives a class mount request, it queries all of its parent nodes in order until the boot ClassLoader. Any node successfully accepts this request, then returns, if all parent nodes are inadmissible, this time by the requested ClassLoader itself to load the class, if still cannot load, throws an exception.

You can use the JVM parameter-verbose:class to print the load log for a class.

(3) Method of class loading



(4) Code example

Create a file in the current directory of the Eclipse project./cp/test/myclass.java

Package Test;public class MyClass {}

Enter the CP directory, compile this file, generate Myclass.class

Javac Test/myclass.java

Run the following code

Package Learning.classloader;import Java.io.bufferedreader;import Java.io.file;import java.io.InputStream;import Java.io.inputstreamreader;import Java.lang.reflect.method;import Java.net.url;import Java.net.URLClassLoader; public class Classloadertest {public static void main (string[] args) throws Exception {try {class. forname ("Test.        MyClass ");        } catch (ClassNotFoundException e) {System.out.println ("Failed to load MyClass");        } File Myclassdir = new File ("./CP");        URLClassLoader SYSCL = (urlclassloader) classloader.getsystemclassloader ();        Method Addurlmethod = URLClassLoader.class.getDeclaredMethod ("Addurl", New Class[]{url.class});        Addurlmethod.setaccessible (TRUE);                Addurlmethod.invoke (SYSCL, Myclassdir.touri (). Tourl ()); Class C = class.forname ("Test.        MyClass ");                        System.out.println ("Loaded MyClass successfully"); URLClassLoader clnew = new URLClassLoader (sYscl.geturls (), syscl.getparent ()); Class C1 = Clnew.loadclass ("Test.                MyClass ");        System.out.println (C.equals (C1));        System.out.println (C.getclassloader ());                System.out.println (C1.getclassloader ());        System.out.println ();        InputStream is1 = C.getresourceasstream ("Myclass.java");        BufferedReader reader = new BufferedReader (new InputStreamReader (IS1));        String s;        while ((s = reader.readline ()) = null) {SYSTEM.OUT.PRINTLN (s);                } reader.close ();        System.out.println ();        InputStream Is2 = C.getresourceasstream ("/test/myclass.java");        reader = new BufferedReader (new InputStreamReader (IS2));        while ((s = reader.readline ()) = null) {SYSTEM.OUT.PRINTLN (s);                } reader.close ();        System.out.println ();        InputStream is3 = Syscl.getresourceasstream ("Test/myclass.java"); reader = new BufferedReader (new InputStreamReader (IS3));        while ((s = reader.readline ()) = null) {SYSTEM.OUT.PRINTLN (s);    } reader.close (); }}


Analysis:
Run the above example, do not add the CP directory to classpath, you can see the first call Class.forName ("test. MyClass ") will fail.
Then add the CP directory to the System class loader (Sun.misc.launcher$appclassloader), or re-add a class loader, set its classpath containing the CP directory, can load the MyClass class normally.

1) different ClassLoader load different class objects from the specified type
In Java, a class is identified by its exact match class name (fully qualified class name), where the exact match class name includes the package name and the class name. But a class in the JVM, with its full name and an instance of the loaded class ClassLoader, is uniquely identified, and classes loaded by the same loader will be placed in different namespaces.
In the above example, C is loaded with the System class loader (Sun.misc.launcher$appclassloader), C1 is loaded with new urlclassloader, and the result of C.equals (C1) is false.

2) Create class loader must set the parent loader correctly
URLClassLoader clnew = new URLClassLoader (Syscl.geturls (), syscl.getparent ());
When creating a new ClassLoader, specify the parent class loader as syscl.getparent (), which is the system ClassLoader's parent, which is the Extension class loader (Sun.misc.launcher$extclassloader).
If you change into
URLClassLoader clnew = new URLClassLoader (Syscl.geturls ());
does not specify its parent, the default parent is the System class loader. The result of this c.equals (C1) will be true. This is due to the class loading rule 1-Parental delegation.

3) Usage of Getresource/getresourceasstream
You can call Getresource/getresourceasstream on both ClassLoader and class. The difference is
*The path specified by Class.getresourceasstream (path), which begins with "/", indicates that the lookup path is classpath, and if it does not start with "/", the lookup path is where class is located.
C.getresourceasstream ("Myclass.java"); --〉 in Test. MyClass location Find Myclass.java
C.getresourceasstream ("/test/myclass.java"); --〉 is found in the path specified by Classpath./test/myclass.java
* The Classloader.getresourceasstream (path) lookup path is classpath.

(5) Contextclassloader

Contextclassloader is a property of thread that can get Thread.CurrentThread (). Getcontextclassloader (), or you can call Setcontextclassloader () setting.
Contextclassloader is just a logical concept, and does not have a class called Contextclassloader.
If a new thread is created, the Contextclassloader is inherited from the creation thread.
When new objects are in the thread, the system ClassLoader is used, and the threading Contextclassloader is not used.

So why do we need Contextclassloader? This is due to the fact that the default rules for loading class do not meet the requirements in some cases.
such as the JDBC API in the JDK and the implementation of the specific database vendor class SPI class loading problem. The classes in the JDBC API are loaded by bootstrap, so if the JDBC API needs to use the SPI implementation class, according to the default rule 2, the implementation class will also be loaded by bootstrap, but the SPI implementation class is not loaded by bootstrap, can only be loaded by ext or app.
When DriverManager needs to load the implementation class in the SPI, it can get contextclassloader and use it to load the classes in the SPI.
Of course, you can not use Contextclassloader, you save a classloader, need to use the place of this classloader can also.


Reference articles
1) http://www.blogjava.net/zhuxing/archive/2008/08/08/220841.html
2) http://shangjava.iteye.com/blog/1097096
3) http://blog.csdn.net/v1v1wang/article/details/6864573
4) Http://www.tuicool.com/articles/A7neua

Java class loading/classloader

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.