Java-与多个类加载器一起使用

问题描述:

我在Java中有一个简单的单例类,如下所示:

I have a simple singleton class in Java that looks like the following one:

public class Singleton{
    private static Singleton instance;

    private Singleton(){}

    public static Singleton getInstance(){
        if (instance == null){
            instance = new Singleton();
        }
        return instance;
    }

    public void doSomething(){
        ...
    }
}

我的代码还包含两个类,从现在开始分别称为A和B,它们都具有以下结构:

My code also contains two classes, from now on called A and B, that both have the following structure:

public class Foo{
    ...
    public void bar(){
        ...
        Singleton.getInstance().doSomething();
        ...
    }
    ...
}

在执行过程中,首先执行类A中的代码,因此它以静默方式实例化单例实例.但是,稍后在执行B的代码时,将再次实例化单例实例,这不是我想要实现的.

During an execution the code in class A is executed first and therefore it silently instantiates the singleton instance. However, later on when B's code gets executed, the singleton instance is instantiated again, which is not what I want to achieve.

经过一番调查,我们发现类A和类B使用了不同的类加载器,这意味着单例类也被加载了两次,从而导致了两个单例实例.

After a little investigation we found that class A and B use a different class loader, which means the singleton class is also loaded twice, resulting into two singleton instances.

我已经在网络上寻找了解决此问题的方法,并找到了几个(非常相似)的页面,例如 http://www.javaworld.com/article/2073352/core-java/simply-singleton.html?page=2 http://snehaprashant.blogspot.nl/2009/01/singleton-pattern-in-java.html .

I've looked for solutions to this issue on the web and found several (quite similar) pages, e.g. http://www.javaworld.com/article/2073352/core-java/simply-singleton.html?page=2 and http://snehaprashant.blogspot.nl/2009/01/singleton-pattern-in-java.html.

但是,在尝试了几种选择之后,我仍然无法使它起作用,主要是因为我真的不知道如何在上面列出的简单代码中应用解决方案.

However, after trying out several options I still can't get it to work, mainly because I don't really know how to apply the solution(s) in the simple code listed above.

所以我的问题是:有人可以为我提供上述问题的代码的实用解决方案(线索),这样无论使用哪种类加载器,单例仅实例化一次?

So my question is: can someone provide me with a (clue to a) practical solution for my code to the problem described above so that the singleton is only instantiated once regardless of the classloader being used?

我怀疑JavaWorld文章中的解决方案是否有效. getContextClassLoader() Singleton.class.getClassLoader()每次都可以返回不同的类加载器.而且,如果您有一个一致的类加载器,那么使用该类的唯一方法就是通过反射.

I doubt the solution in the JavaWorld article works. getContextClassLoader(), and Singleton.class.getClassLoader() can return different classloaders each time. And if you got a consistent classloader, then the only way to use the class would be via reflection.

我想他们希望您替换:

Singleton.getInstance().doSomething();

具有:

try {
    Object instance = getClass("package.Singleton").getMethod("getInstance").invoke(null);
    instance.getClass().getMethod("doSomething").invoke(instance);
} catch (ReflectiveOperationException e) {
    e.printStackTrace();
}

相反,我将看看为什么有多个类加载器.要么将所有代码都放在同一个类加载器下,要么将单例放在两个类加载器的公共父级中,并使子类加载器无法使用该类.

Instead, I would look at why there are multiple classloaders. Either keep all your code under the same classloader, or put the singleton into a common parent of both classloaders, and make the class unavailable to the child classloaders.