Understanding Java ClassLoaders

Koushik Saha's Avatar author of Understanding Java ClassLoaders
ClassLoader is written in Java which makes developers easy to create a custom ClassLoader without the need to understand the internals of the JVM..
Java Runtime Environment uses classloaders to load classes dynamically into the Virtual Machine for execution. A class is a blueprint or a definition which represents a similar kind of objects. It describes the behavior of the objects of its type. In other words, It can be expressed as a named unit of code. An instance of the class holds a particular state defined by its class. A class has its code defined in a .class file when it is compiled from a .java file. It is the responsibility of the class loader to load the class on an “on demand” basis by reading the class file from the file system or from a network. The class loader also performs locating the libraries and loading the classes contained within the libraries.

Each class contains its definition in a public static and final field called class. This java.lang.Class object has a reference to the ClassLoader object that defined this class. The ClassLoader is written in Java which makes developers easy to create a custom ClassLoader without the need to understand the internals of the JVM.

Functions of ClassLoader class



The java.lang.ClassLoader is an abstract class. When a fully qualified name of the class is provided, the class loader determines how the definition of the class can be added to the runtime environment. ClassLoaders can be subclassed by applications that need to extend the manner in which the JVM dynamically loads classes. The java.lang.ClassLoader instance accepts a constructor at the time of instantiation to specify the parent class loader. The virtual machine's system class loader gets assigned as the default parent if no parent class loader is specified.

The ClassLoader class uses a delegation model to search for classes and resources. When a request is made to find a class or resource, the class loader instance delegates the search request to its parent class loader before attempting to find the class or resource itself. This is done to ensure that a class is loaded into the JVM only once and only when it is needed. This means that an object is always associated with its code (class), which when loaded into a JVM, has a specific identity. A class is uniquely identified in a JVM using its fully qualified class name (package.classname) along with the instance of the ClassLoader that loaded the class. Thus, the class instance of a class is mapped in JVM as (classname, package, classloader) where classloader is the instance of the class loader that loaded this class. This means that the same class loaded by two different class loader objects are not same, and not type compatible to each other as well.

Different Variations of ClassLoader



Java class loaders can be mainly classified into following categories:
  • Bootstrap Class Loader - Bootstrap class loader loads the core classes of Java, which are part of java runtime environment i.e. the classes in JAVA_HOME/jre/lib directory. When JVM starts execution, this class loader starts execution first. This class loader is the parent of all class loaders and is implemented in native language. Thats why its implementation might be different across JVMs. Note that the class loader instance of any runtime class returns null. e.g.
    java.lang.Class objClass = java.lang.Object.class;
    System.out.println(“Class Loader: ” + objClass.getClassLoader()); // prints Class Loader: null
  • Extension Class Loader - Extension class loader loads the classes in the extensions directories JAVA_HOME/jre/lib/ext. It can also load classes from any other directory specified by the java.ext.dirs system property. It is implemented by the sun.misc.Launcher.ExtClassLoader class. The parent of the extension class loader is bootstrap class loader.
  • System Class Loader - System class loader loads the classes found on java.class.path, or those jar packages mentioned in the CLASSPATH environment variable. This is implemented by the sun.misc.Launcher.AppClassLoader class. This is the most important class loader from the developer perspective. The parent of the system class loader is the extension class loader.
Note that the above class loader hierarchy corresponds to delegation hierarchy where bootstrap class loader represents the root of the hierarchy. When a request to load a class is made, if the class is not already loaded, the system class loader or any child class loader delegates this request to the parent class loader as it has the reference to its parent initialized through constructor, before trying to load the class itself. The parent in turn consults its parent, and this continues till the bootstrap class loader. So if all the ancestor class loaders cannot find the class, then the current class loader gets involved to load the class.

There are other class loaders provided by Java as mentioned below:
  • java.security.SecureClassLoader - The java.security.SecureClassLoader extends the ClassLoader having additional support for defining classes with an associated code source and permissions which are retrieved by the system policy by default. Secure Class Loaders can be used by classes found in the java.security package.
  • java.net.URLClassLoader - The java.net.URLClassLoader class, which is a subclass of SecureClassloader, can be used to load classes and resources from a search path of URLs referring to directories and JAR files. The URLs will be searched in the order specified for classes and resources after first searching in the parent class loader.
  • java.rmi.server.RMIClassLoader - The java.rmi.server.RMIClassLoader class is responsible for loading the classes from a remote machine via RMI.
  • sun.applet.AppletClassLoader - The sun.applet.AppletClassLoader class is used for loading the applets and their related classes and resources, by communicating with a Web server, into a browser and are defined by the vendor of each Java-enabled browser.

The ClassLoader methods



loadClass() method - The loadClass() method is the entry point to the ClassLoader. This method loads the class with the specified name. This method performs the following steps:
  • Invoke findLoadedClass() to check if the class has been loaded already.
  • Invoke the loadClass() method on the parent class loader. If the parent is null the class loader built-in to the virtual machine is used, instead.
  • Invoke the findClass() method to find the class.
The signature is as follows:
Code:
protected Class loadClass(String name, boolean resolve){}
The name parameter specifies the name of the class that the JVM needs.

The resolve parameter tells the method whether or not the class needs to be resolved by calling resolveClass() method. Class resolution means the task of completely preparing the class for execution.

defineClass() method - The defineClass() method converts an array of bytes, i.e. data that was loaded from the file system or network, into an instance of class Class. It must be resolved before using this class. This method also performs the validity check for security. This method cannot be overridden as this is marked as final. The signature is as follows:

Code:
protected final Class defineClass(String name, byte[] b, int off, int len) {}
The name parameter specifies the name of the class.
The b, off and len parameters are the content in bytes, length and offset of the class data.

findSystemClass() method - The findSystemClass() method finds the class with the specified name and loads it if necessary. This method loads the class through the system class loader. Subclasses of ClassLoader need not usually invoke this method, because most class loaders need to override just findClass().
The signature is as follows:

Code:
protected final Class findSystemClass(String name) {}
The name parameter specifies the name of the class.

findLoadedClass() method - The findLoadedClass() method is called when loadClass() method is asked to load a class, in order to see if the class has already been loaded by this ClassLoader, saving the trouble of reloading a class that has already been loaded. It acts as a cache. The signature is as follows:

Code:
protected final Class findLoadedClass(String name) {}
The name parameter specifies the name of the class.

findClass() method - The findClass() method finds the class with the specified name. This method should be overridden by class loader implementations that follow the delegation model for loading classes, and will be invoked by the loadClass method after checking the parent class loader for the requested class. The default implementation throws a ClassNotFoundException. The signature is as follows:

Code:
protected Class findClass(String name) {}
The name parameter specifies the name of the class.

resolveClass() method - The resolveClass() method will be called depending on the value of the resolve parameter to loadClass() method. This method is called to link the class into the class loader. The signature is as follows:

Code:
protected final void resolveClass(Class cls) {}
The cls parameter specifies the class to be resolved.

Custom Class loaders and their need



Java class loader can be extended to create a custom implementation of the class loader to modify the JVMs class loading process. Any custom class loader should extend java.lang.ClassLoader. In the constructor, parent class loader should be set. Finally, we have to override the findClass() method to provide custom functionality.

A custom class loader can be used to get the following benefits:
  • To load or reload classes at runtime, i.e. loading libraries dynamically, implemented in scripting languages.
  • Associating classes through configuration files.
  • To perform verification before executing untrusted code.
  • To load the bytecode in a different way (i.e. performing decryption logic to load the class).
The appletviewer in JDK and the java enabled browser uses custom class loader to not only load the class but also to take care of security. Similarly, the class loaders in J2EE servers use the “hot deployment” capability, where the application reloads with new class definition without restarting Virtual Machine. So custom class loaders provide additional capabilities over and above general class loading capabilities of a class loader.

Class Loading Errors



There could be scenarios when a class loading process might generate errors. There are a few exceptions that are mentioned below:
  • NoClassDefFoundError - A NoClassDefFoundError is thrown if the Java Virtual Machine or a ClassLoader instance tries to load in the definition of a class and no definition of the class could be found. This means that the searched-for class definition was present when the currently executing class was compiled, but the definition can not be found at runtime. This also means that the class is not in the logical class path or any failure occured to load the dependent class.
  • ClassNotFoundException - A ClassNotFoundException is thrown if the application tries to load a class dynamically using findSystemClass() or loadClass() method of ClassLoader class and no definition for the specified class could be retrieved. This can happen if the class is not present in the logical classpath of the class loader, the application uses incorrect class loader API or any dependent class is not present or visible.
  • ClassCastException - A ClassCastException is thrown if the code has attempted to cast an object to a subclass of which it is not an instance. This can also be thrown when the class loader that loaded the source object (class) is different from the class loader that loaded the target class.

References
  1. Wikipedia: http://en.wikipedia.org/wiki/Java_Classloader
  2. Java Virtual Machine Specification: Java SE 7 Edition, by Tim Lindholm, Frank Yellin, Gilad Bracha, Alex Buckley
  3. Java 7 API Docs: http://docs.oracle.com/javase/7/docs...assLoader.html
  4. Java SE Tutorial: http://docs.oracle.com/javase/tutori...sics/load.html
  5. IBM developerWorks Tutorial: http://www.ibm.com/developerworks/ja...assloader.html
  6. Internals of Java Class Loading, by Binildas Christudas, O’Reilly publication: http://www.onjava.com/lpt/a/5586
shabbir like this