Class-loaders in java play an
important role in Java. They are the pieces that every java developer should be
aware of. In this article we will see the working of a Class-loader in java.
So what exactly is a Class-loader?
Every class-loader is an
Object. An Instance of the class that extends the abstract Class java.lang.ClassLoader. So every class in java is
loaded by one of these instances.
So what does this class-loader do?
The class-loader is the means by
which Java Classes and resources are loaded in the JRE (Java Runtime
Environment).
What does it load?
As we know a Class file
contains the binary representation of a Java Class, which has the executable
byte-codes and references to other classes used by this class. This includes
references to classes to the java API and other references. The Class-loader
locates the byte-codes for the java class that needs to be loaded, read the
byte-codes and creates a instance of java.lang.Class class. Then this class is
made available to the JVM for execution.
Even statements as simple
as String greeting = "hello" or int maxValue =
Integer.MAX_VALUE make use of a class loader.
They require the String class and the Integer class to be
loaded.
Initially only class that needs
to be executed as loaded into the class ,once the execution moves forward the
Classes being referenced are loaded are loaded thus using the lazy loading.
If classes are loaded by the
instances of the class that extends ClassLoader class, then there should be
something that makes the started before this that make the instances of the
Class-loader class. How does this work?
Class-Loader principles
Every ClassLoader in java Works
on 3 Principles,
Delegation: Whenever a Class is to
be loaded, the request is forward to the Parent ClassLoader for loading. The
Child ClassLoader loads the class if Parent ClassLoader cannot find or load
Class.
Visibility: This allows child
ClassLoader to see all classes loaded by the parent ClassLoader but the Parent
ClassLoader cannot view classes loaded by the Child ClassLoader.
Uniqueness: This allows loading a
Class exactly once by taking help of delegation and ensures that the
ClassLoader does not re-load the class that is already re-loaded by the Parent.
How Classes are loaded?
Here is an excerpt from the
java.lang.ClassLoader
package java.lang;
public abstract class ClassLoader {
public Class
loadClass(String name);
protected Class defineClass(byte[]
b);
public URL getResource(String name);
public Enumeration getResources(String name);
public ClassLoader getParent()
}
The loadClass(String name) is
the most important method above, which takes the fully qualified name of the
class to be loaded as String and returns an object of class Class.
The next important method is
the defineClass(byte b[]) which actually materialize the Class. The byte array
parameter is the byte code of the Class which is loaded from Disk.
The getParent() method returns
the Parent Class-loader.
getResource and getResources return URLs to actually
existing resources when given a name or a path to an expected resource.
So consider if I we check the
code,
Public class A {
Public void createB() {
B
b=new B();
}
}
In the above snippet, when we
say B b=new B(),a couple of things happen here. The creation of B instance is B b =
A.class.getClassLoader().loadClass(“B”).newInstance().
So every Object created is associated with
its own class (A.Class in this case) and every Class is associated with its own
ClassLoader.
Class-Loader
Hierarchy
Whenever a JVM starts a bootstrap
ClassLoader is started first. This is the parent Class-loader for all Classes.
Its responsibility is to load Core Classes from java.lang package and other use
full runtime Classes to the memory first. We can say
that the bootstrap ClassLoader is the one which does not have a parent Class
Loader.
The next one of the extension
class-loader which is responsible for loading classes from all the jar file
available in the java.ext.dirs path and files available in JRE/lib/ext
location.
The next is the Application
Class loader which is very important for a developer. This ClassLoader is
responsible for loading classes from directories and jar files specified by the
CLASSPATH environment variable, java.class.path system property or –classpath
command line. This is the child of the extension Class-loader.
Contest Class Loader: In the
newer versions of java, there is something called as Context Class Loader which
is used with threads. A thread's context class loader is, by default, set to
the context class loader of the thread's parent. The Context class loader of a
thread is set to the Class-loader that loaded the application. The context
class loader can load the classes that the application can load. This is
normally used by the java Runtime such as RMI to load classes and resources on
behalf of the application.
Endorsed Standard Override
Mechanism: The Endorsed Standard
Override Mechanism says that if
we have a newer version of JAXP class which we want to load but Since this
class is already being loaded by the bootstrap ClassLoader from the rt.jar, in
order to overcome we can place this new version in a location and access that location
by passing an argument as –Djava.endorsed.dir=<Path to Location of Jar>
Here is the Class-Loader
hierarchy,
Request for a Class by Client
Lets see how the class-loader
thing works when a Client requests to load a Class.
1. A check is performed to see
if the requested class is already loaded by the Current Class Loader. If that
is loaded it is returned back and used. The JVM will cache all the classes that
are loaded by the Class-loaded so a Class which was loaded once will not be loaded
again.
2. If the class is not already
loaded, the request is delegated to the Parent Class-Loader before the check to
the Current Class-loader fails. The delegation can move to the top level
(bootstrap Class loader) until no further delegation can be done.
3. So if the parent
Class-loader also cannot load the class, the Current Class-loader will then try
to search for the requested class in some defined locations such as the
bootstrap searches in the location specified in the sun.boot.class.path system property.
And Application class-loader will search in the classpath location.
4. If the class is still not
found, a java.lang.ClassNotFouncException is thrown.
Does Classes in Class-Loader see?
Classes loaded by a
Class-loader can see other Classes loaded by the same Class-loader. Classes
inside a Class-loader cannot see Classes loaded by other Classes.
JMV keepts track of the classes
loaded by a Class-loader. This is achieved by name-space technique by which
every Class-loader in a Java application will have its own Name-space(
java.lang.*) and classes loaded in one name –space cannot see classes loaded by
other Name-spaces.
There are certain restrictions
where we can load multiple class-loaders in the java application and load the
same class from multiple class-loaders. At this point , the class will know
that there is another version available.
What If I create a custom class in a name-space?
Since we said that classes are
loaded by the name-space and classes loaded in one class-loader cannot view classes
loaded by other Class-loader. What if I create a class in java.util Package?
Even if we create a custom
class with a same package, java only grants access to a Class in the same
package which gets loaded by the same Class-loader. In the above case even if
we create a Custom class with a same package name, the class will be loaded by
the user-class loader.
Container Class-Loader
This class loader hierarchy
happens when a JVM starts but the hierarchy may differ when we use J2EE
containers. In containers, every ear application deployed will be having its
own Class-loader and more over ever war file inside the ear will have its
class-loader. The web class-loader will load the classes in the local
class-loader and the task is delegated to the Parent Class loader only when
Classes cannot be loaded (as Specified in Servlet Specification).
Some containers allows to web
modules to load classes from the location specified instead of loading classes
from the Parent Class Loader. In Weblogic, we can use
<Prefer-web-inf-class> element in the weblogic.xml file which allows jar
to be loaded from the WEB-INF location even though a version of the jar is
loaded by the parent Class-Loader. These cases arise with the logging libraries
where the container holds a version and application ships with a different
version.
This is normally done by
overriding the loadClass() method of the java.lang.ClassLoader Class.
We will see some Class Loader
case Studies like Tomcat, Weblogic and JBoss in next articles.
No comments :
Post a Comment