18

例如,我有Singleton静态字段类instance

public class Singleton {

    private static Singleton instance;

    // other code, construct, getters, no matter    
}

我可以用两个不同的类加载器加载这个类两次。我怎么能避免呢?这是不安全和危险的。

另外,如果我将实例设置为 null,它会为两个类都设置为 null 吗?

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

2 回答 2

29

如果你想要一个Singleton跨类加载器的真实值,那么你需要一个共同的父类来加载有问题的类,或者你需要自己指定类加载器。

更新:从下面@Pshemo 的评论来看,下面博客中的相当一部分内容可能直接来自JavaWorld 文章。我已经留下了博客条目,因为它可能仍然可以帮助某人,但值得知道内容最初来自哪里。

原文: 有一篇文可以让你做到这一点”(虽然我没试过!),而且看起来还算合理

按照下面的要求,我上面的链接中的代码片段 - 我建议您访问该博客以获取完整的上下文:

private static Class getClass(String classname) throws ClassNotFoundException {
    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    if(classLoader == null) 
        classLoader = Singleton.class.getClassLoader();
      return (classLoader.loadClass(classname));
}
于 2013-03-01T11:53:39.153 回答
2

Properties这是一个滥用extends事实的 hack Map,一个旧的不幸的设计决定。

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().

PropertiesHashtable基于的,所以它是线程安全的(根据文档)。所以可以使用props.computeIfAbsent(). 但我更喜欢这种方式。

另请阅读:Java 系统属性的范围

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

于 2017-11-22T23:52:41.740 回答