Using two different classloaders to load two children of the same class

667 Views Asked by At

I have two classes, Child1 and Child2, children of the class Parent. The class Parenthas a static member, and the two children classes have a static method run() using this static member. As I have to call Child1.run() and Child2.run() inside the same application, I want that each of the child class can access its own version of the static member of the parent class.

I know that it would be easier to put the static member of the parent class into the children class, but I can't modify the source code of the classes.

I read around that I shoud use two different classloaders, but I don't understand how. Can someone explain me how to use classloaders to achieve the result I mentioned, maybe with some example code?

2

There are 2 best solutions below

4
On BEST ANSWER

Yes, what you ask is possible using two different ClassLoaders. You need to compile your classes (Parent, Child1 and Child2), but they should not be in the same classpath location as the class you're invoking them from (call that class Main).

Instead, put them somewhere on your disk in a directory or put them in a jar file.

From that location, you can create multiple classloaders, and you can use the method loadClass to load classes with it; and you can use reflection to invoke methods, like the method run on it.

import java.lang.reflect.*;
import java.net.URL;

public class Main {
    public static void main(String[] args) throws Exception {
        URL childAndParentClassesLocation = new URL("c:/Somewhere/On/Your/Disk");
        ClassLoader cl1 = new URLClassLoader(new URL[] { childAndParentClassesLocation }, Main.class.getClassLoader());
        ClassLoader cl2 = new URLClassLoader(new URL[] { childAndParentClassesLocation }, Main.class.getClassLoader());

        Class child1 = cl1.loadClass("packagename.Child1");
        Class child2 = cl2.loadClass("packagename.Child2");

        Method child1Run = child1.getMethod("run");
        Method child2Run = child2.getMethod("run");

        child1Run.invoke(null); // Invoke run method on Child1
        child2Run.invoke(null); // Invoke run method on Child2
    }
}

P.s. this is bad design for a general purpose application, but you didn't say you were making a general-purpose application. So I don't see any reason to dumb down SO by dissuading interesting questions that help explain how the JVM works.

0
On

Well, purpose of class level member/static member is to have one copy per JVM. what you are suggesting in your question is defeating the above purpose.

If that is the case, you should achieve it with instance level members. See this