2013-03-01 5 views
11

Z. B Ich habe Klasse Singleton mit statischem Feld instance:Singleton-Klasse mit mehreren verschiedenen Classloader

public class Singleton { 

    private static Singleton instance; 

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

ich diese Klasse verschiedenen Classloader zweimal mit zwei laden kann. Wie könnte ich es vermeiden? Es ist unsicher und gefährlich.

Wenn ich die Instanz auf null setze, würde es dann für beide Klassen auf null gesetzt?

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

Wenn Sie wirklich ein Singleton-Design-Muster erreichen wollen, dann folgen Sie [enum type] (http://en.wikipedia.org/wiki/Singleton_pattern#The_Enum_way) in Java - "* ein Single-Element-Enum-Typ ist die beste Möglichkeit, ein Singleton zu implementieren * " – Lion

+7

das Enum-Muster würde das Vorhandensein einer Instanz pro Klassenlader nicht verhindern, oder? – keuleJ

+0

Über Singletons: http://weblogs.java.net/blog/kirillcool/archive/2005/08/how_single_is_y.html – keuleJ

Antwort

24

Wenn Sie einen echten Singleton über Classloader wollen, dann müssen Sie einen gemeinsamen Elternteil die betreffende Klasse zu laden, oder Sie müssen die Klassenladeprogramm selbst bestimmen.

Update: Aus dem Kommentar von @Pshemo unten kann ein gutes Stück des Inhalts im Blog unten direkt von einer JavaWorld Article kommen. Ich habe den Blog-Eintrag verlassen, da es immer noch jemandem helfen kann, aber es ist wissenswert, woher der Inhalt ursprünglich stammt.

Original: Es gibt einen blog Eintrag, gibt Ihnen die Möglichkeit dies zu tun "(! Obwohl ich es versucht haben), und es sieht ziemlich vernünftig

von unten hier einen Code-Schnipsel angefordert meine Link oben - ich schlage vor, Sie den Blog besuchen, obwohl für den vollständigen Kontext:

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

Schöne Antwort! Es wäre noch besser, wenn Sie hier ein Codebeispiel der Lösung mit einem Kredit für den verknüpften Artikel einfügen würden. –

+0

Bitte Code-Beispiel einbeziehen. – bsiamionau

+0

Code-Snippet wie gewünscht :-) –

0

Dies ist ein Hack mißbrauchen die Tatsache, dass Properties erstreckt Map, eine alte bedauernswerte Entscheidung

012.
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; 
    } 
} 

Dies könnte parametrisiert werden, aber dann wäre die Initialisierung faul und gehen Sie zu getSingleton().

Properties ist Hashtable -basiert, so ist es Thread sicher (gemäß der Dokumentation). So könnte man props.computeIfAbsent() verwenden. Aber ich mag es so mehr.

Auch hier lesen: Scope of the Java System Properties

Ich schrieb es einfach und es gibt eine Chance, etwas, das ich dies von der Arbeit das würde verhindern, übersah es.

+0

Ein Bug da drin ... reparieren –

Verwandte Themen