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 thejava.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.
super bhayya
ReplyDelete