web-dev-qa-db-ja.com

いくつかの異なるクラスローダーを持つシングルトンクラス

たとえば、静的フィールドSingletonを持つクラスinstanceがあります。

public class Singleton {

    private static Singleton instance;

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

このクラスは、2つの異なるクラスローダーを使用して2回ロードできます。どうすればそれを回避できますか?それは危険で危険です。

また、インスタンスをnullに設定した場合、両方のクラスでnullに設定されますか?

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

クラスローダー全体で真のSingletonが必要な場合は、問題のクラスをロードするための共通の親が必要です。または、クラスローダーを自分で指定する必要があります。

更新:以下の@Pshemoからのコメントから、以下のブログのコンテンツのかなりの部分が直接 JavaWorld Article から来ている可能性があります。 =。それでも誰かを助けるかもしれないので、私はブログエントリを残しました、しかしコンテンツが最初にどこから来たのかを知ることは価値があります。

オリジナル:これを行う方法を提供する ブログ エントリがあります」(私は試していませんが!)、そしてそれはかなり合理的に見えます

以下で要求されているように、上記のリンクからのコードスニペット-完全なコンテキストについては、ブログにアクセスすることをお勧めします。

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

これは、PropertiesMapを拡張するという事実を悪用したハックであり、これは古い不幸な設計上の決定です。

_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システムプロパティ のスコープ

私はそれを書いたばかりですが、これが機能しなくなるような見落としがあった可能性があります。

2
Ondra Žižka