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.
January 12, 2011 at 12:01 pm
Another effort through the ups & downs of Java classloaders! 🙂 Good one. I would have given you our classloader which solves your problem straight away 😛 Ofcourse, that wouldn’t have given this blog post 😉
January 13, 2011 at 4:59 am
Thanks Anil… 🙂
February 25, 2011 at 2:44 pm
Great tip ! Thanks for sharing it.
February 25, 2011 at 6:05 pm
Interesting post..
Maybe I am missing something but you say that you want to dynamically load classes.
How is it still dynamic if you have to specify the class that you want to create and invoke methods on it? If classes change name then you still have to edit your code and recompile to execute the new changes.
February 27, 2011 at 5:24 am
Java’s reflection package supports loading the classes dynamically. This loading happens during the Run time instead of the load time. The code in the post shows that we have defined the class and the method names. But this need not be that. We can get the class names and the methods from any properties files and dynamically load the same. In this case you wont have to edit the code and recompile the same.
February 26, 2011 at 10:21 pm
The current context classloader is most often the one you want to be using rather than the system classloader.
February 27, 2011 at 5:25 am
Agreed 🙂
December 16, 2011 at 5:58 pm
I Still get ClassNotFoundException with above code, any idea what could be the root cause?
This is URL :jar:file:C:\Documents and Settings\Administrator\My Documents\XXX.jar!/IXXX
Please suggest
April 21, 2013 at 11:50 pm
Even if my comment comes 2 year late but Thank you a lot ! you saved me ! 😀
February 14, 2014 at 6:30 am
Wow! Thank you so much. I spent so much time looking on other forums trying to dynamically load my custom jar file. This is very straightforward and clear. You are a life saver!!
February 20, 2014 at 11:22 am
Its really nice post but what if we want to access a class from the jar without loading by its name.. For one reason, I may have lot of classes in the jar and I want all be avaialble for me in class-path. how do we do that?