Class Loading is one of the basic concept of any programming language. Once you know this concept, you understand rest the Java concepts far better and it makes your life easier. You remember getting ClassNotFoundException any time in your code? Well, that’s it !! It’s the time to know why and how did you get it. So lets start from ‘What’ and reach till ‘How’ in the journey of Java ‘Class Loader’. Are you ready to begin ?
What is a Class Loader
As the name suggests – A Class Loader is something that loads the classes at runtime in Java. It is responsible for finding and loading class files into JVM. It is the job of Class Loader to load the class files from a source location and the source location can be a file system, network or any other place. Java code is compiled into class file by java compiler and then JVM executes the byte code written in class file.
Class Loading Phases and Process
Not able to visualize what actually happens? Lets first understand what is the process which takes place when we say ‘class is loading’.
There are three phases involved in the loading of a class: loading, linking, and initializing. Lets look at all three in detail and try to visualize with the below diagram:
The loading phase consists of locating the required class file and loading in the bytecode. Within the JVM, the loading process gives a very basic memory structure to the class object. Methods, fields, and other referenced classes are not dealt with at this stage. As a result, the class is not usable.
So the required class gets loaded in this phase with basic memory structure but still ‘unusable’.
This phase is at the heart of loading and contains three stages in it.
a) Bytecode verification – The class loader does a number of checks on the bytecode of the class to ensure that it is well formed and well behaved.
b) Class preparation – This stage prepares the necessary data structures that represent fields, methods, and implemented interfaces that are defined within each class. (Sounds better ?)
c) Resolving – In this stage, the class loader loads all the other classes referenced by a particular class. The classes can be referenced in a number of ways: Super classes, Interfaces, Fields, Method signatures, Local variables used in methods etc.
During this phase, any static initializers contained within a class are executed. At the end of this phase, static fields are initialized to their default values. (That’s it really)
Once all these phases are over, a class is fully loaded and is ready for use. So the linking process is performed by the JVM at runtime and the classes are loaded into the JVM ‘based on need’. Also, in case the loaded class depends on another class, then that class is loaded as well. There is also a possibility of lazy loading in a class and therefore some parts of the class loading process may be done on first use of the class rather than at load time.
When a Java application is launched, the first class to run (or the entry point into the application) is the one with public static void method called main(). This class usually has references to other classes, and all attempts to load the referenced classes are carried out by the class loader.
So hope by now you understand what all happens in the process of class loading. Now let’s get into some crucial details related to this.
Class Loaders Types
There are three default class loader used in Java and every class loader has a predefined location, from where they load class files.
1) Bootstrap :
A bootstrap class loader is responsible for loading the core classes of the Java runtime. This class loader only loads classes that are found in the boot classpath. It is responsible for loading standard JDK class files from JRE/lib/rt.jar for example : java.lang, java.util etc. Bootstrap is the parent of all class loaders in Java and does not have any parents of it.
2) Extension :
JVM has an extension class loader responsible for loading classes from standard extension APIs which are located at JRE/lib/ext or any directory denoted by java.ext.dirs. It loads the classes which are ‘extension’ of core java classes. Extension ClassLoader delegates class loading request to its parent – ‘Bootstrap’ and if unsuccessful, loads class form jre/lib/ext directory or any other directory pointed by java.ext.dirs system property. Extension ClassLoader in JVM is implemented by sun.misc.Launcher$ExtClassLoader.
3) System or Application class loader :
It loads application specific classes from a general class path(CLASSPATH environment variable, Class-Path attribute of Manifest file inside JAR file) as well as your application classes. Application class loader is a child of Extension ClassLoader and it’s implemented by sun.misc.Launcher$AppClassLoader class. Also, except Bootstrap class loader, which is implemented in native language(mostly in C) all Java class loaders are implemented using java.lang.ClassLoader.
Now to know how these three class loaders work and support each other, we need to know the three principles on which ClassLoader in Java works: delegation, visibility and uniqueness.
Due to Delegation principle, a class loader forwards request of a class loading to parent class loader and only loads the class if parent is not able to find or load class. For example: There is a application specific class called Goyalsbit.class which needs to be loaded. So the request of loading it will go to Application ClassLoader. Application ClassLoader will delegate loading to its parent Extension ClassLoader which will further delegate to Bootstrap class loader. Bootstrap will look for that class in rt.jar and as that class will not be found there, request will go to Extension class loader which looks on jre/lib/ext directory and will try to locate the class there. If class is found there than Extension class loader will load that class and Application class loader will never load that class but if it’s not loaded by extension class-loader than Application class loader loads it from Classpath in Java.
Visibility principle allows child class loader to see all the classes loaded by parent ClassLoader, but parent class loader can not see classes loaded by child.
Uniqueness principle allows to load a class exactly once, which is basically achieved by delegation and ensures that child ClassLoader doesn’t reload the class already loaded by parent.
Since there is more than one class loader, they are represented in a tree whose root is the bootstrap class loader. Each class loader has a reference to its parent class loader. When a class loader is asked to load a class, it consults its parent class loader before attempting to load the item itself. The parent in turn consults its parent, and so on. So it is only after all the ancestor class loaders cannot find the class that the current class loader gets involved. In other words, delegation model is used.
Now if you have come so far, don’t forget to put down the comments. If it has made an addition to your knowledge, share it further too.