Classes loading on Virtual Machine is a hidden process of any programming language. Most of the developers do not bother about it. Because this is the responsibility of frameworks to load their respective classes to run Virtual Machine and application on it. But believe me, this is really very important to know about classloaders and classloading mechanism. If you are writing higher end applications or frameworks, which has wide scope of work to do, there might be chance, you need to write your own custom classloaders for your applications. Lots of Java based frameworks have implemented their custom classloaders, which solve their concerned problems. Here we specifically talking about Java classloaders, Lets we discuss about classloading mechanism in Java Virtual Machine.
Class Loading on JVM
Classloading is a process to load required classes on Virtual Machine. Only after loading required classes your application can run on JVM. There are two types of classloading.
- Eager Classloading is process of loading all classes comprising the source of application before run the application on VM. Application can take some time to run on VM, because classloaders will first load all classes to VM and after that they will run application on VM.
- Lazy Classloading is process of loading classes, at first active use of class rather that loading them on start-up of application on VM.
The first active use of class occurs, when one of the following event occurs:
- An instance of that class is created.
- An instance of one of its subclass is initialized.
- One of its static fields is initialized.
These two are the types of classloading on VM. But its totally depends of JVM vender that what types of classloading they are providing with their JVM. Note that, JVM provided by IBM supports both types of classloading but JVM provided by Oracle (Sun) is only support Lazy classloading.
Before describe more about classloading mechanism in JVM, I would like to tell you somethings about
java.lang.ClassLoader class, which will help you to under classloading mechanism. According to JavaDoc, the class
ClassLoader is an abstract class. If you want to create your own custom class loader for your application or framework then you can extend your classloader class from
java.lang.ClassLoader class. There are methods available in
ClassLoader class to load and define classes from file system.
ClassLoader class load any class by its binary name and return
java.lang.Class class object. Every
java.lang.Class object contain reference of it
java.lang.Class objects for array classes are not created by classloaders, but are created automatically as required by the Java runtime. The
ClassLoader for an array class, as returned by
Class.getClassLoader() is the same as the classloader for its element type; if the element type is a primitive type, then the array class has no
ClassLoader class uses a delegation model to search for classes and resources. Each instance of classloader has an associated parent classloader. When requested to find a class or resource, a
ClassLoader instance will delegate the search for the class or resource to its parent class loader before attempting to find the class or resource itself. The Virtual Machine’s built-in class loader, called the “bootstrap classloader“, does not itself have a parent but may serve as the parent of a
Class loaders that support concurrent loading of classes are known as parallel capable classloaders and are required to register themselves at their class initialization time by invoking the
ClassLoader.registerAsParallelCapable() method. Note that the
ClassLoader class is registered as parallel capable by default. However, its subclasses still need to register themselves if they are parallel capable.
In environments in which the delegation model is not strictly hierarchical, class loaders need to be parallel capable, otherwise class loading can lead to deadlocks because the loader lock is held for the duration of the class loading process (see loadClass methods).
Normally, the Java Virtual Machine loads classes from the local file system in a platform-dependent manner. For example, on UNIX systems, the virtual machine loads classes from the directory defined by the CLASSPATH environment variable.
However, some classes may not originate from a file; they may originate from other sources, such as the network, or they could be constructed by an application. The method
defineClass() converts an array of bytes into an instance of class
java.lang.Class. Instances of this newly defined class can be created using
Java has it own classloaders hierarchy to load classes on JVM. Java has three in-built classloaders, which are shown bellow in classloaders hierarchy diagram.
As you can see in above diagram, these three core classloaders communicate with each other through there hierarchy protocols, which I would mention later-on in this article. Now lets understand about particular classloader individually, their hierarchy and responsibilities:
- Bootstrap classloader : Bootstrap classloader is core native classloader of Java. This is the topmost classloader of classloaders hierarchy, it wouldn’t be wrong, if would say, this is the parent of every classloader in Java, like
java.lang.Objectclass is parent class of every class in Java. Because this is native classloader, therefore it’s implementation could be vary with different JVMs. Native classloaders are mostly implemented in C language. Bootstrap classloader is responsible to load all available classes in rt.jar file, which is located at $JAVAHOME/jre/lib/rt.jar
- Extension classloader: Extension classloader come done next to Bootstrap classloader, in other word, this is child classloader of Bootstrap classloader. It is implemented by
sun.misc.Launcher$ExtClassLoaderclass. This classloader is responsible to load all classes available in ext folder, which is located at $JAVAHOME/jre/lib/ext/*.jar or any other directory specified by java.ext.dirs system property.
- System classloader: System classloader is also known as Application classloader. It is implemented by
sun.misc.Launcher$AppClassLoaderclass, which come done next to Extension classloader. This is child classloader of Extension classloader. The main responsibility of this classloader is to load all available classes in $CLASSPATH or java.class.path location.
- User Defined ClassLoaders: User defined or Custom classloader are those classloaders, which are defined by developers itself for their applications or frameworks. If you want to create your own classloader then you have to extend your classloader class by
java.lang.ClassLoaderclass. These custom classloaders will come done under System classloader in hierarchy. Their class loading responsibility would be defined by the developers.
This is very important and interesting to understand, how does JVM load any class internally. Till now you almost clear about ClassLoaders, their hierarchy and their individual responsibilities. Now its time to understand communication between classloaders, their overall class loading mechanism and workflow. Now have smile, lets go little deep and understand it better.
Whenever JVM instantiate any class, then JVM will load this class, this is known as Lazy classloading. JVM uses a delegation model to load classes. Basic idea of delegation model is that classloader has a parent classloader, when classloader load a class, it first delegate the search for class to its parent classloader, before attempting to find the class itself.
Classloading is a recursive process, When a classloader get request to load a class, it will initiate class loading. First of all it pass the request to it parent classloader, if that parent class loader has any of its parent classloader then it will pass request to its parent classloader and so on. Such way topmost classloader in hierarchy will first search that class in its directory and its cache ( Every ClassLoader maintain its own cache ), whether this class is already been loaded by this classloader, if yes then classloader will return class from cache, otherwise classloader will find that class in its directory. If class exist there in directory, it will store that class in its cache and return that class to its child classloader and so on. In other hand, if parent classloader did not find that class in its directory and cache, it will throw
ClassNotFoundException. Now its child classloader catch this exception and try to find that class in its directory location. The same procedure will go on until that class would not found by any classloader in that hierarchy. If still that class is not available in overall hierarchy of classloader, eventually classloader, who initiate class loading will throw
ClassNotFoundException and stop the execution.
There are few observations about classloading, which are important in this classloading mechanism:
- Parent classloader has always opportunities to load class first.
- Each classloader maintain their own cache and check any class first in its cache, if it is not available in cache then check it in its directory and try to load it.
- It is ensure that one classlaoder can only see classes loaded by itself or by its parent classloaders, but not by its children and siblings classloaders.
ClassLoader Call Flow
In previous section of this article you have learnt about classloading mechanism. Now you are aware about how does classloading take place internally in JVM. In this section, I would like to explain, how custom classloader are implemented by extending
java.lang.ClassLoader class and what is the
ClassLoader’s methods call flow to load and define a class in JVM.
There are three important methods of
ClassLoader class, which play significant role to load and define a class in JVM. These methods of
ClassLoader class are given bellow:
- public Class<?> loadClass(String name) throws ClassNotFoundException;
- protected Class<?> findClass(String name) throws ClassNotFoundException;
- protected final Class<?> defineClass(String name, byte b, int off, int len) throws ClassFormatError;
ClassLoader is created, it is assigned a parent
ClassLoader. As per parent delegation model, when client invoke
loadClass(String name) method of
ClassLoader class, it will call the
loadClass method of parent
ClassLoader, where is classloading algorithms is implemented. Before JDK 1.2,
loadClass method was abstract, every
ClassLoader was required to provide its own classloading algorithm. But later on it is observed that class loading is a critical, complicated and important for JVM, therefore since JDK 1.2 JVM introduced parent delegation model and provide default implementation for
loadClass method. After that
loadClass method invoke
findClass(String name) method of
ClassLoader class. Every Custom or User Defined
ClassLoader should override
findClass(String name) method to specify custom location, where classes need to be search before loading. The
findClass method invoke search for given class in specified location, if class found, it read that class and return bytecodes of the class. This bytecodes of class is passed as
byte array to the
defineClass(String name, byte b, int off, int len) method,
defineClass method returns
java.lang.Class class, which define that given class. This
java.lang.Class instance can be used to instantiate that class in Java application. This is the way, how a class get loading and defined in JVM.
This article describes, how important a classloading mechanism is to understand, if you a Java developer. This articles explain entire important aspects regarding classloading and ClassLoaders. After reading this article you can create your own
ClassLoader, which suites to your applications. Hope you would like this article. This article encourages you to go more deep in concepts.