Java Unfolded

– The inner view

Class loaders

Introduction:

Class loading is a very important concept in Java and this should be understood by all the java developers. This article gives you a deeper understanding about class loading, not restricted to three JDK class loaders [Bootstrap, Extension and Application class loaders] and delegation between them.

Basics about Class loaders:
Java has three main class loaders which loads classes into JVM. Bootstrap class loader, Extension class loader[sun.misc.Launcher$ExtClassLoader] and Application classLoader[sun.misc.Launcher$AppClassLoader] which loads classes based on delegation principle.

Diagram – 1:

classLoader-Basic

[Bootstrap]Class loader has a load method [Class<?> loadClass(String className)] which is designed to load classes into JVM from Runtime jar [rt.jar], If any one want to write their own class loader they have to extend ClassLoader and need to override load class method. Fortunately we have two more class loaders in Java they are called ExtClassLoader and AppClassLoader which are implemented to load classes from JRE/lib/ext and CLASSPATH respectively. Extension class loader reads its path from System property “java.ext.dirs” and Application classLoader reads from “java.class.path”.

When there is a requirement of class loading, the current class loader dedicates the request to its parent and that class loader to its Parent and so on up to Bootstrap class loader[i.e when a class loader’s parent is null] gets the request.
so the parent class loader will check whether the class is loaded already or not, if not loaded it tries to load the class, if it is unable to load the class it gives the chance to its derived class loader.

Class loader Architecture :
Class loader will come into picture in below scenarios.
1. C:\>java Helloworld the Helloworld.class is loaded into JVM by the class loader.
2. When a class is referred from the other class.

In both the cases, how JVM make sure that the referred class is loaded already or it has to be loaded at that moment?

There must be some look-up to have a track about all the classes loaded into JVM, when you try to see the loadClass() method in ClassLoader.java, the implementation is in a native method, it is implemented in C language. In the native implementation it maintains a HashTable kind of data structure to keep track of all the classes loaded by the JVM.

Before looking into the look-up table or its key string, we will ask some questions ourselves:
Have you ever think, why we can not have two classes with the same name in the same package? where it is allowed in different packages? and Some times we get ClassCastException saying Class pkg.Abc cannot be cast to Class pkg.Abc?

As we know a fully qualified name of a class is derived as Class Name + Package Name + Class loader instance name [which has loaded it].
This fully qualified name is used as a key in HashTable/LookUp in JVM. So to differentiate a class from the other, above three things matters, most of the times ClassLoader instance name is over looked by the developers.

Diagram – 2 :

ClassLoader-2Final

Sample code to illustrate the concept.

package wordpress;

import java.io.IOException;
import java.io.InputStream;

/**
 * @author Nag
 *
 */
public class ClassLoaderDemo {

	static class LocalClassLoader extends ClassLoader {

		@Override
		public Class<?> loadClass(String className) throws ClassNotFoundException {
			if (!"wordpress.ClassLoaderDemo".equals(className)) {
				// If the loading class is not wordpress.ClassLoaderDemo then dedicate the loading activity to parent class loader
				return super.loadClass(className);
			}
			try { // Read the class and load it using defineClass method, you can find the method definition in java.lang.ClassLoader
				InputStream in = ClassLoader
						.getSystemResourceAsStream("wordpress/ClassLoaderDemo.class");
				byte[] b = new byte[10000];
				int len = in.read(b);
				in.close();
				return defineClass(className, b, 0, len);
			} catch (IOException e) {
				throw new ClassNotFoundException();
			}
		}
	}

	public static void main(String[] args) throws Exception {
		ClassLoader localClassLoader = new LocalClassLoader();

		Class<?> klass = localClassLoader.loadClass("wordpress.ClassLoaderDemo");
		// Fully qualified class name for any class is pkgName + ClassName + ClassLoaderName
		System.out.println(klass.getName() + " : " +klass.getClassLoader());
		System.out.println(ClassLoaderDemo.class.getName() +" : "+ ClassLoaderDemo.class.getClassLoader());

		Object cld1 = klass.newInstance();
		Object cld2 = (ClassLoaderDemo) cld1;

		System.out.println(cld1 == cld2);
	}
}

Output:

wordpress.ClassLoaderDemo : wordpress.ClassLoaderDemo$LocalClassLoader@7e820d53
wordpress.ClassLoaderDemo : sun.misc.Launcher$AppClassLoader@1830e4a7
Exception in thread “main” java.lang.ClassCastException: wordpress.ClassLoaderDemo cannot be cast to wordpress.ClassLoaderDemo
at wordpress.ClassLoaderDemo.main(ClassLoaderDemo.java:42)

Some more information :
When we refer a class from some other class, JVM gets the class loader of current class and delegates the loading request to it.
In case the class loader or its parent class loaders did not get the class it throws NoClassDefFoundError, which can not be recovered as it is an ERROR not an Exception.

When ever we want to load any class dynamically, we can make use of Class.forName() method which is there in Class, it also dedicates the loading request to the current class loader, if the class is not available for class loaders to load, it throws ClassNotFoundException, with this we can recover by surround it with try catch blocks and we can load some other class in the absence of first/unavailable class.

you can write your suggestions and queries to me @ nag.wordpress@gmail.com

Leave a comment