My first post on Java Technologies… 🙂

One of the initial challenges I faced when I started coding in Java was writing a JMS client, about which I will write shortly. But today there is another interesting challenge to talk about. Loading the classes dynamically.

I had a requirement of taking a bunch of jars as an input from the user and use them in my code. Sounds simple??

Java provides a feature where u can edit the system environment variables using System object. So can’t we edit the classpath and solve the issue? No!! the problem here is, the system class loader is initialized at the very beginning of the start up sequence and it copies the classpath in to it. So if you dynamically change the classpath it won’t be useful as the system class loader would have already read the old classpath and loaded the classes accordingly.

There should be some approach to solve this…. Yes!! There is… Class Loaders… Before getting in to the details, let me give a brief description of the class loaders.

Loading a class is managed by the Class Loaders in JVM. Bootstrap Loader is the main loader which loads all the basic java classes during the bootstrap. As most of the Java programmers already know… there is no separate step for linking in java. When JVM loads a class, using a class loader, a lot happens along with the linking. All the operations like decoding of the binary format, compatibility checking, verifying the sequence of operations and constructing the java.lang.Class instance will be handled by JVM itself. This feature in Java brings a lot of flexibility to load the classes at runtime even though it adds a lot of overhead when the classes are initially loaded. Now, bootstrap isn’t the only class loader with JVM. As mentioned before, it also has system class loader which loads all the classes from the general classpath. It also loads all the application classes.

Apart from these, JAVA also provides a feature where applications can define their own class loaders. Each class constructed by the class loader is owned by the loader. This post is all about how to write your own class loader, how to add jars to system loader and the things you need to understand before using any of the approaches…

To begin with… the import statements that you need to add are…

import java.net.URL;
import java.net.URLClassLoader;

I need a Uniform Resource Locater(URL) to point my Jar. We can create it like below..

URL myJarFile = new URL(“jar”,””,”file:”+myfile.getAbsolutePath()+”!/”);

The first argument is the protocol that is being used to source the data. There are multiple protocols that are supported like http, https, file, ftp and jar. The second argument is the host where the source is. And the third argument is the absolute location of the source. This statement defines the URL that points us to the jar.

We can add this URL to the class loader so that all the classes in the jar can be used. We can either define a new Class loader or get the instance of the system class loader and add the URL to it. I ll show you both the methods here…

getSystemClassLoader() method can be used to get the System class loader object.

URLClassLoader sysLoader = (URLClassLoader)ClassLoader.getSystemClassLoader();

To add a jar to the system class loader, we need to add the URL to sysLoader object. Once we have the System class loader we need to get the declared method and invoke the same as below…

Class sysClass = URLClassLoader.class;
Method sysMethod = sysClass.getDeclaredMethod(“addURL”,new Class[] {URL.class});
sysMethod.setAccessible(true);
sysMethod.invoke(sysLoader, new Object[]{myJarFile});

Every class object gives all the hooks to access basic metadata of the class like the package it is in, its super class, all its interfaces, constructors, fields, methods etc..
As you see above, First I tried to get the instance of the Method(addURL) that is declared in the URLClassLoader class and then I am trying to invoke the method with the jar file as an argument. The purpose of this method is to add the URL to the system class loader which will make the all the classes in the URL visible to the application.

Using System class loader would be appropriate for simple application. But for some complex applications, like application servers, where we don’t want one application interfering another defining a separate class loader for each application makes sense. Java provides a facility to derive the class loaders from java.lang.ClassLoader. Every class loader has a reference to its parent. So whenever the class loader tries to load a class, it checks if the parent has already loaded it. So any class loaded by a class loader would not only be visible to itself but also to all its decedents. By default System class loader is the parent class loader for all user defined class loaders.

Now to create a Class loader

URLClassLoader cl = URLClassLoader.newInstance(new URL[] {myJarFile});

Now the jar is added to the class loader. The next step is to load the class, create an instance of it, get the method that needs to be executed and invoke it. Let us assume that we have a class myclass which has a method “String printMe(String, String)” that needs to be invoked.

The source looks like below…

Class MyClass = cl.loadClass(“com.mycomp.proj.myclass”);
Method printMeMethod = MyClass.getMethod(“printMe”, new Class[] {String.class, String.class});
Object MyClassObj = MyClass.newInstance();
Object response = printMeMethod.invoke(MyClassObj,”String1″, “String2”);

What if I need a non-default constructor to create myclass object like “myclass(String)”? As I said before the java provides all the hooks to get the meta info from the jar. So create the object of such a class we would need to get the constructor and create an instance from it like below

Constructor MyClassConstruct = MyClass.getConstructor(new Class[] {String.class});

Object MyClassObj= MyClassConstructConstruct.newInstance(“myString:);

Once the object is created using the constructor, you can invoke all the methods of that class like above.

These features of java is a great tool to build flexible code that can be hooked at the run time without any need for the source code links between classes.

Advertisements