简体   繁体   English

使用两个不同的类加载器来加载相同类的两个孩子

[英]Using two different classloaders to load two children of the same class

I have two classes, Child1 and Child2 , children of the class Parent . 我有两个班, Child1Child2 ,班里的孩子Parent The class Parent has a static member, and the two children classes have a static method run() using this static member. Parent类有一个静态成员,而两个子类都有使用此静态成员的静态方法run() 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. 由于必须在同一应用程序中调用Child1.run()Child2.run() ,因此我希望每个子类都可以访问其自己的父类静态成员版本。

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? 有人可以解释我如何使用类加载器来实现我提到的结果,也许带有一些示例代码?

Yes, what you ask is possible using two different ClassLoaders. 是的,您可以使用两个不同的ClassLoader进行询问。 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 ). 你需要编译的类( ParentChild1Child2 ),但他们不应该在相同的类路径中的位置,你是从(调用类调用它们的类Main )。

Instead, put them somewhere on your disk in a directory or put them in a jar file. 而是将它们放在目录中磁盘上的某个位置,或放在jar文件中。

From that location, you can create multiple classloaders, and you can use the method loadClass to load classes with it; 在该位置,您可以创建多个类加载器,并可以使用loadClass方法加载类。 and you can use reflection to invoke methods, like the method run on it. 您可以使用反射来调用方法,例如在其上run的方法。

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
    }
}

Ps this is bad design for a general purpose application, but you didn't say you were making a general-purpose application. ps这对于通用应用程序来说是不好的设计,但是您并没有说您在制作通用应用程序。 So I don't see any reason to dumb down SO by dissuading interesting questions that help explain how the JVM works. 因此,我认为没有任何理由通过劝说有助于解释JVM工作原理的有趣问题来简化SO。

Well, purpose of class level member/static member is to have one copy per JVM. 好吧,类级别成员/静态成员的目的是每个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 看到这个

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM