Loading a class more than once using java’s built in ClassLoader is not possible because:
Builtin ClassLoader always checks if a class has already been loaded. If it is, it simply does nothing and returns.
Hence to reload a class, you have to use your custom ClassLoader.
Code to reload a class using custom ClassLoader is as follows:
public class Test {
public static void main(String[] args) throws Exception {
//notice different instances of ClassLoader. Reason follows below.
Class<?> c1 = new TestClassLoader().loadClass("Test");
Class<?> c2 = new TestClassLoader().loadClass("Test");
//print class name for first instance
System.out.println(c1);
//print class name for second instance
System.out.println(c2);
// confirm that the two class instances are different by comparing their
// references. This should print false if the instances are different
// which means that the class is loaded twice
System.out.println(c1 == c2);
}
}
class TestClassLoader extends ClassLoader {
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
// load other classes normally using System ClassLoader
if (!name.equals("Test")) {
return super.loadClass(name);
}
InputStream in = null;
try {
// get input stream linked to this class
in = ClassLoader.getSystemResourceAsStream(name + ".class");
int data = in.read();
// initialize buffer
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
// loop over data till more data is available
while (data != -1) {
// write data to buffer
buffer.write(data);
data = in.read();
}
// convert to byte array as this is the format accepted by
// defineClass method
byte[] classData = buffer.toByteArray();
// converts a byte array to a instance of class java.lang.Class
return defineClass(name, classData, 0, classData.length);
} catch (IOException e) {
throw new ClassNotFoundException();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
// ignore
}
}
}
}
}
Code is self-explanatory by its comments. We shall explore some other facts in the following lines:
Let’s tweak in:
- Every loaded class has to be linked also. ClassLoader’s resolve() method does this automatically.
- resolve() method does not allow any ClassLoader instance to link the same class twice. Therefore we had to create two different ClassLoader instances to load the class.
- Loading a class more than once using the same ClassLoader instance will give the below error: Exception in thread “main”
java.lang.LinkageError: loader (instance of TestClassLoader): attempted duplicate class definition for name: "Test"
- resolve() method is final, hence cannot be overridden.