Tuesday, January 12, 2010

How to Write a Custom Class Loader to Load Classes from a Jar

A custom class loader is needed when the developer needs to load classes from some custom repositories, to implement hot deployment features and to allow unloading of classes.

According to Java2 class loading system, a custom class loader should subclass java.lang.ClassLoader and overrride findClass() method which is responsible for loading the class bytes and returning a defined class.

Following code is a custom class loader which loads classes from jars, inside the directory called "jar".

public class JarClassLoader extends ClassLoader {
    private String jarFile = "jar/test.jar"; //Path to the jar file
    private Hashtable classes = new Hashtable(); //used to cache already defined classes

    public JarClassLoader() {
        super(JarClassLoader.class.getClassLoader()); //calls the parent class loader's constructor
    }

    public Class loadClass(String className) throws ClassNotFoundException {
        return findClass(className);
    }

    public Class findClass(String className) {
        byte classByte[];
        Class result = null;

        result = (Class) classes.get(className); //checks in cached classes
        if (result != null) {
            return result;
        }

        try {
            return findSystemClass(className);
        } catch (Exception e) {
        }

        try {
            JarFile jar = new JarFile(jarFile);
            JarEntry entry = jar.getJarEntry(className + ".class");
            InputStream is = jar.getInputStream(entry);
            ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
            int nextValue = is.read();
            while (-1 != nextValue) {
                byteStream.write(nextValue);
                nextValue = is.read();
            }

            classByte = byteStream.toByteArray();
            result = defineClass(className, classByte, 0, classByte.length, null);
            classes.put(className, result);
            return result;
        } catch (Exception e) {
            return null;
        }
    }

}

This code can be improved to
* Load classes from any jar inside the directory
* Dynamically pick up classes if the jar is updated (by keeping a modified time field)

23 comments:

Asiri Rathnayake said...

Hi Kalani, make sure your implementation doesn't break resource loading. I think I came across this issue when I wrote a JarClassLoader for one of my projects. As I remember, if you have stuff like Class.getResource(String) which tries to load jar - local resource, they won't work out of the box with this JarClassLoader.

kalani Ruwanpathirana said...

Hi Asiri, Thanks for pointing out. Yea this class loader doesn't override ClassLoader's findResource() method. In my case I was just testing to achieve dynamism only in class loading. I guess this kinda thing will resolve that.

public URL findResource(String name) {
try {
File file = new File(jarFile);
String url = file.toURL().toString();
return new URL("jar:"+url+"!/"+name);
} catch (Exception e) {
return null;
}

}

Just a quick test. There may be more prof ways.

janandith uditha jayawardena said...

Hi Kalani, Nice post. Simple and sweet.

kalani Ruwanpathirana said...

Thank you Janandith :)

Iñaki López said...

Hello,

I'm developing a library that tries to imitate the Java Web Start functionality, and for doing that I am creating a custom class loader.

I used your code as starting point and now my class loader works perfect.

Thanks a lot!

Greetings from Spain.

kalani Ruwanpathirana said...

Nice to hear that. Thanks.

Chhote Lal Prasad Gupta said...

Hi Kalani,

It is really a good article for a custom class loader. Your expanation is very good and very precise.Thanks for posting a good article on net.

Thanks
Chhote

Manoj said...

Hi Kalani,

A very good piece of work. The sample code works great. I guess you should also cover about your finding on the classloader aspect of Java.

Keep up the good work and keep it posting too :-)

kalani Ruwanpathirana said...

Thanks Manoj and Cchote...sure, I'll be posting:)

Hasan Ceylan said...

Helllo Kalani,

Doesn't URLClassLoader already does this with improvments you have suggested...

In the HELL of Cyber Mania said...

Nice tutorial on the image splitting and concatenation.

allister allon said...

the site provides the solutions specifically targeted towards business directories. and conjointly provide free business listings and free business advertising to all or any small business homeowners.
Custom Directory

Sachin FromDev said...

nice post, just stumble across your blog from stackoverflow ref..

Sumit said...

kalani ji,,,i am in btech and my project is how to design class loader in java please help me .....my email id kumarsumit912@gmail.com...
if their is any code related to this please send me and also how to run.

Supreeth Kumar said...

Hi kalani,
The post is really very good.
I have very less knowledge on class loader, so please correct me if am wrong. I understand the reason why you have overridden findClass(As your intend is to load the class from jar). But why is that you have overridden loadClass in your classloader?
Isn't the base class(ClassLoader) does the similar implementation? if we use the default constructor to create classloader the parent loader would be systemclassloader. So you reduce rewriting this logic in your implementation of findClass.

PS :
I am not commenting on your code, it's just that I am trying to understand better. Please do provide your thoughts :)

wimal_perera said...

Hi Kalani,

Its a great post to see how a class loader works internally, especially how the internals of a jar file can be read and how defineClass() method could be used.

But isn't it possible to achieve the same thing in your code by doing something like;

java.io.File jarFile = new java.io.File("path_to_your_jar_file");
java.net.URL fileURL = jarFile.toURL();
URLClassLoader clsLoader = new URLClassLoader(new URL[] {fileURL});

Or am I missing something important here?


Dilbert said...

This post helped me at need of the hour.

Thanks a ton

anne said...

Custom writings should cover the entire coursework activities and this should be stated by the professor before he or she delivers the custom writing to the students for undertakings this site will help you so.

angel mar murillo said...

http://www.bestcustomessay.org/essays will not provide your personal details to other people at any circumstance.

manoj said...

Hi Kalani,
How to take care of laoding multiple jars by the custom classaloder

Pass it as URL[] ?

Regards
Manoj

Lauren Lebow said...

Good instruction, this is really a big help to all computer geeks out there. Hope you can write more mightystudents essay like this one.

hemcoined said...

I used your code as starting point and now my class loader works perfect.
Gangway

Prethesh Kumar Bhalotia said...

First of all I would like to thank for this nice articles. It really helped me a lot writing a custom loader.

Still I have some questions on this. With out our custom loader can't we load the classes from out custom jar?

Little confused on this.

Can you please share your answers on my mail id pretheshkumarbhalotia@gmail.com

Thanaks a ton Kalani.

Related Posts with Thumbnails