Monday, November 17, 2014

All You Need to Know about Class-loaders

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