Dynamically Reloading a Modified Class
This example demonstrates how to reload a modified class without
restarting the application. The technique involves loading the
reloadable class with a separate class loader. Each time the class
needs to be reloaded, it is loaded using a new class loader and the
previous class loader (with the old class) is abandoned.
It is important that the reloadable class not be on the
classpath. Otherwise, the class will be loaded by some parent of the
new class loader rather than by the new class loader itself. Once this
happens, the class cannot be reloaded.
Since the class cannot be on the classpath, it is not possible
to use the class name directly in the code (otherwise a
ClassNotFoundException would be thrown during start up). To circumvent
this problem, the reloadable class must be made to implement an
interface and the interface name is used in the code.
This example places the reloadable class in a subdirectory
called dir, which is not on the classpath. Here is the reloadable
class:
To compile this class, it is necessary to tell the compiler
the location of MyReloadableClass. Since, for this example,
it is located in the parent directory, the following command will compile
this class:
Here's the code that reloads the reloadable class:
Here's some code that tests the reloadable class (a more realistic
routine would periodically check the timestamp on the file). After the
example is started, change the string returned by myMethod() and
recompile.
public class MyReloadableClassImpl implements MyReloadableClass {
public String myMethod() {
return "a message";
}
}
> java -classpath .. MyReloadableClass
// Get the directory (URL) of the reloadable class
URL[] urls = null;
try {
// Convert the file object to a URL
File dir = new File(System.getProperty("user.dir")
+File.separator+"dir"+File.separator);
URL url = dir.toURL(); // file:/c:/almanac1.4/examples/
urls = new URL[]{url};
} catch (MalformedURLException e) {
}
try {
// Create a new class loader with the directory
ClassLoader cl = new URLClassLoader(urls);
// Load in the class
Class cls = cl.loadClass("MyReloadableClassImpl");
// Create a new instance of the new class
myObj = (MyReloadableClass)cls.newInstance();
} catch (IllegalAccessException e) {
} catch (InstantiationException e) {
} catch (ClassNotFoundException e) {
}
try {
while (true) {
reloadMyReloadedClass();
System.out.println(myObj.myMethod());
Thread.sleep(5000);
}
} catch (Exception e) {
}
Post a comment