Java 具有多个不同类装入器的Singleton类

Java 具有多个不同类装入器的Singleton类,java,singleton,classloader,Java,Singleton,Classloader,例如,我有一个带有静态字段实例的类Singleton: public class Singleton { private static Singleton instance; // other code, construct, getters, no matter } 我可以用两个不同的类加载器加载这个类两次。我怎样才能避免呢?这是不安全和危险的 另外,若我将instance设置为null,这两个类的instance会设置为null吗 Singleton singl

例如,我有一个带有静态字段
实例的类
Singleton

public class Singleton {

    private static Singleton instance;

    // other code, construct, getters, no matter    
}
我可以用两个不同的类加载器加载这个类两次。我怎样才能避免呢?这是不安全和危险的

另外,若我将instance设置为null,这两个类的instance会设置为null吗

Singleton singleton = Singleton.getInstance();
singleton = null;

如果希望跨类加载器实现真正的
单例
,则需要一个公共父级来加载所讨论的类,或者需要自己指定类加载器

更新:从下面@Pshemo的评论中可以看出,下面博客中相当一部分内容可能直接来自某个网站。我留下了这篇博文,因为它可能仍然对某些人有帮助,但值得知道内容最初来自何处

原件: 有一个条目为您提供了一种方法(尽管我还没有尝试过!),它看起来相当合理

根据以下要求,这里是我上面链接中的代码片段-我建议您访问博客,了解完整内容:

private static Class getClass(String classname) throws ClassNotFoundException {
    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    if(classLoader == null) 
        classLoader = Singleton.class.getClassLoader();
      return (classLoader.loadClass(classname));
}

这是一种利用
属性
扩展
映射
这一事实的黑客行为,这是一个古老的不幸的设计决策

public final class JvmWideSingleton
{
    private static final JvmWideSingleton INSTANCE;

    static {
        // There should be just one system class loader object in the whole JVM.
        synchronized(ClassLoader.getSystemClassLoader()) {
            Properties sysProps = System.getProperties();
            // The key is a String, because the .class object would be different across classloaders.
            JvmWideSingleton singleton = (JvmWideSingleton) sysProps.get(JvmWideSingleton.class.getName());

            // Some other class loader loaded JvmWideSingleton earlier.
            if (singleton != null) {
                INSTANCE = singleton;
            }
            else {
                // Otherwise this classloader is the first one, let's create a singleton.
                // Make sure not to do any locking within this.
                INSTANCE = new JvmWideSingleton();
                System.getProperties().put(JvmWideSingleton.class.getName(), INSTANCE);
            }
        }
    }

    public static JvmWideSingleton getSingleton() {
        return INSTANCE;
    }
}
这可以参数化,但是初始化将是延迟的,并转到
getSingleton()

属性
基于
哈希表
,因此它是线程安全的(根据文档)。因此可以使用
props.computeIfAbsent()
。但我更喜欢这种方式

请在此阅读:


我刚刚写了它,有一种可能是我忽略了一些东西,这可能会阻止它工作。

如果你真的想实现一个单例设计模式,那么遵循Java——“单元素枚举类型是实现单例的最佳方式“枚举模式不会阻止每个类加载器都有一个实例,是吗?关于单例:不幸的是,枚举可以由不同的类加载器进行,正如您所想象的,这可能会导致各种各样的问题。回答不错!如果您在这里包含一个解决方案的代码示例,并将其归功于链接文章,那就更好了?如何调用它来确保单例在类加载器中保持单例?还有一个非常好的web资源可以理解这个问题。你确定Sneha是这篇文章的作者(或者至少是关于类加载器的部分)?据我所见,这篇链接文章发表于2009年1月8日,但它看起来与2003年4月25日出版的相当古老的文章的一部分一样。博客上的帖子甚至包含这样一句话:“前面的方法可以用来代替
Class.forName()
”,这似乎是断章取义的,因为前面没有使用
Class.forName()
方法,虽然这在javaworld中是有意义的,因为示例10使用了反射。作者是Kirill Grouchnikov,标题是“你的singleton实例有多单身?”其中有一个bug。。。固定