Reputation: 241
Is it possible to load multiple versions of the same class into the JVM. I have a version of the class "XYZ" loaded in the main thread and I have multiple children threads doing some work. I want to load different versions of class "XYZ" in to children threads.
Is this doable? I was thinking of creating a new context class loader for each of the children threads and use this context class loader to load a different version of the class. For now I am using URLClassLoader for context class loaders but that does not seem to work. Do I have to create a custom class loader to the do the job?
Here is the code I have so far.
final Thread builderThread = new Thread("Child Thread " + buildToken) {
@Override
public void run() {
futureTask.run();
}
};
try {
URL url = new URL("file:///path to the jar file");
URLClassLoader classLoader = new URLClassLoader(new URL[]{url});
classLoader.loadClass("XYZ");
builderThread.setContextClassLoader(classLoader);
}
The reason why I want to have different versions of the class is because I want to have different values for the static fields in the class "XYZ".
Upvotes: 2
Views: 1210
Reputation: 116908
The reason why I want to have different versions of the class is because I want to have different values for the static fields in the class "XYZ".
This really seems like a hack to me. Do you really have no other way to inject different values into this class?
How about passing some sort of Context
instance for each thread and convert your class to use the settings from the Context
instead of from static
fields. You could also use a ThreadLocal
so each thread would get the static field information from there instead.
Loading different versions of the class is going to be extremely hard (if not impossible) to debug. The only time I've ever heard of folks using multiple class loaders is when you have security concerns (often in a web server environment) and there is a deliberate point to having separation between the web classes and the outer admin classes.
Upvotes: 0
Reputation: 10308
Yes, it is possible, and you're on the right track with URLClassLoader
. The scope of your classloaders will be determined by the scope you want the static
fields to have. For example, if each task or thread should have its own copy of those fields, then each task or thread must have its own classloader.
There are a couple other issues to be aware of. First, the class you want to load multiple times must not be found on the system classpath. This is because classloaders exist in a hierarchy, and delegate to their parent before attempting to load a class themselves. If the system classloader finds the class, it will load it only once, and other classloaders will use the class loaded by the system classloader.
Second, the JVM will treat each loading of the class as a distinct class, despite the fact that they're all identical. This means that instances of the dynamically loaded class must be confined to the scope of their classloader. If each task has its own classloader, then instances cannot be passed between tasks. And obviously you cannot publish instances to the rest of the app, because the rest of the app uses the system classloader, which must not know about the class. (You can get around this somewhat if the dynamically loaded class has a superclass or superinterface that the system classloader does know about. Then you can publish the instance as that type.)
Upvotes: 3