Sunday, 16 June 2013

Java ClassLoader



How ClassLoader Works in Java?


  • A class loader is an object, a java program that is responsible for loading classes. 
  • It is the class responsible for finding and loading class files at runtime. 
  • The Java ClassLoader is a part of the Java Runtime Environment (JRE) that dynamically loads Java classes into the JVM (Java Virtual Machine). 
  • Generally classes are loaded only on demand. Because of the help provided by Java Class Loaders the JRE system does not required to know about files and file systems. 
  • The JVM needs a class, so it asks the ClassLoader, by providing the name, and the ClassLoader attempts to return a Class object that represents that class. 
  • In JVM, each and every class is loaded by some instance of a java.lang.ClassLoader
  • The ClassLoader class is located in the java.lang package and we are free to subclass it to add their own custom ClassLoader functionality for class loading.

Questions: - What is Class Loading?


Answers: - The term “class loading” refers to the process of locating the bytes for the given class name and converting them into a Java Class instance. All java.lang.Class instances within a JVM start life as an array of bytes, structured in the class file format defined by the JVM specification.

ClassLoader.loadClass() is the entry point to the ClassLoader.

Its signature is as follows:

Class loadClass(String name) - Loads the class with the specified binary name.

ClassLoaders:-

A general Java program running from command line involves three ClassLoaders – Bootstrap, Extensions ClassLoader and System - Classpath ClassLoaders. When JVM is started, it forms an initial class loader hierarchy with the combination of these ClassLoaders.




ClassLoader Hierarchy



Bootstrap ClassLoader

Another name of bootstrap class loader is primordial ClassLoader. This ClassLoader is responsible to load JDK core java classes from rt.jar. This is the parent/super of all the ClassLoaders. The uniqueness of this ClassLoader is that it is not actually a subclass of java.lang.ClassLoader but is implemented by the JVM itself. Whenever a new JVM is started by typing java TestClass, the "bootstrap ClassLoader" is responsible for loading key Java classes like java.lang.Object and other runtime code into memory first. The runtime classes are packaged inside of the JRE\lib\rt.jar file. We can’t find the details of the bootstrap ClassLoader in the Java docs, since this is a native implementation. For the same reason, the behavior of the bootstrap class loader will also differ/changes across JVMs.

Extension ClassLoader

The extension ClassLoader is responsible to load classes from the jars kept in the JRE extension directory (<JAVA_HOME>/jre/lib/ext, or any other directory specified by the java.ext.dirs system property. This ClassLoader provides a standard mechanism to introduce new functionality beyond the core java classes. So a developer can add his own application .jar files or whatever libraries he might need to add to the classpath to this extension directory so that they will be loaded by the extension class loader. Extension ClassLoader in JVM is implemented by sun.misc.Launcher$ExtClassLoader. This is the immediate child of bootstrap ClassLoader, but calling getParent() on this instance will always return null, since the bootstrap loader is not an actual ClassLoader instance.

System-Classpath ClassLoader or Application ClassLoader 


System-Classpath ClassLoader is a child of Extension ClassLoader. This ClassLoader is responsible for loading all of the classes from CLASSPATH environment variable or corresponding to java.class.path system property or –cp or –classpath command line settings. It is implemented by sun.misc.Launcher$AppClassLoader class

User-Defined ClassLoader 


It allows applications to customize class loading as per their requirements.


Examples of some other JDK ClassLoaders:-
  • sun.applet.AppletClassLoader
  • java.net.URLClassLoader
  • java.rmi.server.RMIClassLoader
  • java.security.SecureClassLoader

Phases of Class Loading:-

The complete class loading process can be categorized into three phases:-

Loading: - During loading, the required class file is searched in specified classpaths. If the file is available in the specified classpath then it is read and the bytecode is loaded. This process gives a basic memory structure to the class object, and at this stage the methods, fields and other reference classes are not known.

Linking: - This process can be broken down into three stages, as this is a bit complex phase.

  • Bytecode verification: - ClassLoader does a number of checks on the bytecode.

  • Class preparation: - In this stage, ClassLoader prepares the necessary data structures that represent fields, methods and implemented interfaces that are defined within the class.

  • Resolving: - ClassLoader loads all the other classes which is being referenced by a particular class. The classes can be referenced in a number of ways:
      • Super classes
      • Interfaces
      • Field types
      • Method signatures
      • Local variables used in methods

Initializing: - During this phase any static initializers contained within a class are executed so that, static fields are initialized to their default values. 
Note:- It is interesting, that class loading can be performed in a lazy manner and therefore some parts of the class loading process may be done on first use of the class rather than at load time.


 






Class Loading Phases details




Java ClassLoader operation works on 3 principles:

Delegation

This principle tells, if a particular class is already not loaded, then the ClassLoader delegates the request to load that class to their parent ClassLoaders. This delegation continues until the top of the hierarchy is reached. Suppose we want to load HelloWorld.class which is application specific class, then the first request for loading this class will come to System-Classpath ClassLoader or Application ClassLoader, which will delegate to its parent Extension ClassLoader and again which further delegates that request to Bootstrap ClassLoader. Bootstrap ClassLoader will look for that class in rt.jar and since that class is not available there, then Bootstrap ClassLoader delegates the request to Extension ClassLoader and it tries to find on jre/lib/ext directory and locate this class there, if class is found there than Extension class loader will load that class and System-Classpath ClassLoader will never try to load that class but if it is not loaded by Extension ClassLoader than System-Classpath ClassLoader loads it from Classpath

  



Delegation principle



Visibility

This principle tells that Classes loaded by parent ClassLoaders are visible to child ClassLoaders but not vice versa. It means that if class HelloWorld.class is loaded by Application class loader than trying to load class HelloWorld.class explicitly by using Extension ClassLoader will throw exception.

In order to check the visibility principle we have following program:-

import java.util.logging.Level;
import java.util.logging.Logger;

public class VisiblityPrincipleTestInClassLoader {

            private final static Logger logger = Logger
                                    .getLogger(VisiblityPrincipleTestInClassLoader.class.getName());

            public static void main(String args[]) {
                        try {
                                    /**
                                     * Displaying ClassLoader of VisiblityPrincipleTestInClassLoader
                                     * class
                                     */
                                    System.out.println("VisiblityPrincipleTestInClassLoader.class.getClassLoader() : "
                                                            + VisiblityPrincipleTestInClassLoader.class
                                                                                    .getClassLoader());

                                    /**
                                     * Again trying to explicitly load
                                     * VisiblityPrincipleTestInClassLoader class by using Extension
                                     * Class Loader as we are calling getParent() method and Extension
                                     * ClassLoader is the parent of AppClassLoader or System-Classpath
                                     * ClassLoader.
                                     */
                                    Class.forName("VisiblityPrincipleTestInClassLoader", true,
                                                            VisiblityPrincipleTestInClassLoader.class.getClassLoader()
                                                                                    .getParent());
                        } catch (ClassNotFoundException ex) {
                                    logger.log(Level.SEVERE, "ClassNotFoundException", ex);
                        }
            }

}

Result:-

VisiblityPrincipleTestInClassLoader.class.getClassLoader() : sun.misc.Launcher$AppClassLoader@1050169
Jun 16, 2013 3:42:34 PM VisiblityPrincipleTestInClassLoader main
SEVERE: ClassNotFoundException
java.lang.ClassNotFoundException: VisiblityPrincipleTestInClassLoader
            at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
            at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
            at java.security.AccessController.doPrivileged(Native Method)
            at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
            at java.lang.Class.forName0(Native Method)
            at java.lang.Class.forName(Class.java:264)
            at VisiblityPrincipleTestInClassLoader.main(VisiblityPrincipleTestInClassLoader.java:26)


Uniqueness

This principle tells that when a ClassLoader loads a class, the child ClassLoader in the hierarchy should never load the class again. This follows from the delegation principle as we know that a ClassLoader always delegates class loading to its parents. The child ClassLoader will only try to load in case if parent ClassLoader hierarchy fails to load that class. Thus the uniqueness of the class is maintained.
 

There are many ways to access a ClassLoader:-



  • class.getClassLoader();
  • classLoader.getSystemClassLoader();
  • Thread.currentThread().getContextClassLoader();
  • Or Thread. getContextClassLoader();
  • An application specific method to retieve a class loader.


Explicit/Implicit Class Loading:-


  • Implicit Class Loading: - It occurs when the class is loaded as a result of reference, inheritance or initialization. In this type of loading, class is either return through the delegation model or from the cache.
  •  Explicit Class Loading:- It occurs when a class is loaded by using some specific methods which is as below:-

classLoader.loadClass("VisiblityPrincipleTestInClassLoader");

Here classLoader is an instance of java.lang.ClassLoader class.

Class.forName(“VisiblityPrincipleTestInClassLoader”);

If the class whose name is specified as the parameter for loading it explicitly, is already loaded then ClassLoader returns the reference to it from cache else ClassLoaders will follow the delegation model to load the class.

Question: - Why to write a custom ClassLoader?

Answer: - For the following purposes, we can write the custom ClassLoaders:-
  • Security: - Our ClassLoaders should be responsible to examine classes for having a digital signature before they are handed over to the JVM.
  • Encryption: - For providing the facility to our ClassLoaders that decrypts class files on the fly, so that our class files on disk are not readable by someone by using the decompiler.
  • To allow class loading from alternative repositories:- For integrating a feature into out ClassLoaders, so that it will be able to load the class files that are not in the classpath or it will be able to load classes from over the network.
  • Archiving: - If we want to distribute our code in a unique format or with some special compression.
  • For Loading of specific versions: - it helps in selectively loading classes from specific locations.
  • To allow the unloading of classes if required for any specific application.

About Custom ClassLoader

Generally, J2EE servers implement custom ClassLoader to enable features such as hot redeployment and application independence. Normally, the class loaded by custom ClassLoader is unknown to current class loader, we can't cast the object to real type, we can refer it as an object or refer it using its interface.


Questions:- How to write a custom ClassLoader?


Answer:- Minimal steps to implement a custom ClassLoader
  •        We need to extends the ClassLoader and needs to override loadClass () and findClass ()   method.
  •        Check whether the class has already been loaded, if already loaded, just return it.
  •        If not, check to see whether its parent class loader can load this class.
  •        If not, then we have to implement the logic to load it by its own.
  •        Define the class (call parent's method directly).
  •        Check whether the class has to be resolved (linked), and in that case, resolve it (call parent's method directly).
  •        Return the Class object to the caller.

Question:- What is JAR hell?

Answer:- JAR hell is a term which is very much similar to DLL hell which is used to describe all the various ways in which the classloading process can end up with not working.
 

1 comment: