In this post I want to discuss how runtime class reloading can be done in java using user defined class loaders. The following is a simple example that demonstrates how classes can be reloaded at runtime in Java. This is done using a different user defined class loader than that originally loaded the class. The following two java classes should be on the classpath of the java command.

package com;
import java.io.*;
import java.net.*;
 
public class TestReload {
    private TestClass reload() {
        URL[] urls = null;
        try {
            // Convert the file object to a URL
            File dir = new File("C:\\programs\\projects\\");
            URL url = dir.toURL();        // file:/c:/almanac1.4/examples/
            System.out.println(url);
            Runtime.getRuntime().exec("javac C:\\programs\\projects\\com\\*.java");
            urls = new URL[]{url};
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            ClassLoader cl = new URLClassLoader(urls);
            Class cls = cl.loadClass("com.TestClassImpl");
            return (TestClass) cls.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
 
    public static void main(String[] argsv) {
        System.out.println("sys out");
        TestReload testReload = new TestReload();
        while (true) {
            System.out.println(testReload.reload().getMessage());
            try {
                Thread.sleep(5000);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
 
// Test class the implementation of this class will be out side of class path
package com;
public interface TestClass {
	public String getMessage();
}

Now place the TestClass and TestClassImpl in a path other than the java class path and compile them. Now run the original TestReload and change the message, you will see the changes picked up at run-time :). Bear in mind that I chose not have the class to be reloaded specifically in class path to avoid confusion. This is perfectly acceptable and two different class loaders can load same class.

package com;
public class TestClassImpl implements TestClass {
    public String getMessage() {
        return "Change me";
    }
}

Grails development is breeze with runtime class reloading for controllers, domain and service classes etc at run time. JavaRebel is a promising tool that enables this functionality to java users and is a great productivity gain. This tool uses class instrumentation and java agents to achieve run-time class loading that is more efficient and faster.

Resources:
http://mindprod.com/jgloss/reloading.html
http://www.exampledepot.com/egs/java.lang/ReloadClass.html

Leave a Reply