3

As per the singleton design pattern, there can only exist one instance of the Singleton class throughout the "application". However, this definition assumes that the Singleton class itself is loaded once by a single classloader. But, in a theoretical multi-VM environment, there is a possibility for the same Singleton class being loaded by multiple classloaders.

How can a developer ensure that only a single instance is available across the entire multi-VM environment? Is there a way of ensuring the class-loading to happen via a single classloader only?

ProgFan666
  • 93
  • 1
  • 7
  • 4
    There is no way to ensure that two VM on different machines which don't communicate with each other don't load the same class twice. Can you clarify what you mean by multi-VM? – Peter Lawrey Jan 28 '13 at 22:46
  • 1
    http://stackoverflow.com/questions/2810378/how-to-create-a-cross-process-singleton-class-in-java – digitaljoel Jan 28 '13 at 22:47
  • 1
    You're confusing classloaders and VMs. You can have multiple class loaders in a single JVM. – JB Nizet Jan 28 '13 at 22:48
  • You have to write an exclusivity clause into the contract, with financial penalties for noncompliance. – Hot Licks Jan 28 '13 at 22:52

3 Answers3

4

Short answer? in a non-managed environment you can't. That's the fallacy of the Singleton pattern, it really is impossible to enforce in a normal environment. Think of it: a class object exists in the context of a class loader, there can be several of those living in the same VM. And there can be several VMs living inside the same node. And several nodes can be part of the same application. Of course each one of those class objects will create a single instance of the class if they were implemented as singletons, but there can (potentially) be many class objects.

As mentioned in Oleg Mikheev's answer, recent versions of the Java EE specification have provisions for singleton session beans; I'm not familiar with their implementation details, but I'm left wondering if they're really, really singletons: a single instance existing across a clustered application - or if they're only a logical abstraction, with several instances existing across different nodes.

Arjan Tijms
  • 37,782
  • 12
  • 108
  • 140
Óscar López
  • 232,561
  • 37
  • 312
  • 386
0

Well, I assume you are talking about java. The java language itself does not provide a good way to define the Singleton pattern IMO. That is why when I want to use specific patterns in my code, such as that one, I extend it using AspectJ.

With AspectJ you can actually "catch" every call to any constructor and make sure that you are always returning the same object, thus having a singleton, no matter what.

In case you want it, here is the protocol code in AspectJ:

package singleton.aspectJ;
import java.util.Hashtable;
import java.util.Map;

import org.aspectj.lang.annotation.AdviceName;

/**
 * Defines the general behavior of the Singleton design pattern.
 *
 * Each concrete sub-aspect of SingletonProtocol defines the Singleton
 * property for one or more types.
 *
 * The sub-aspect defines two things: <ol>
 *
 *   <li> what types are <i>Singleton</i> <br>
 *
 *   <li> what classes can access the <i>Singleton</i>'s constructor (if any)
 *        despite its property
 * </ol>
 *
 * for this implementation we choose to illustrate that it is not necessary
 * to provide a factory method for accessing the <i>Singleton</i>
 * instance (like <i>getSingleton()</i>). The regular
 * constructor may be used instead.
 *
 * @author  Jan Hannemann
 * @author  Gregor Kiczales
 * @author Pedro Martins
 * @version 1.1.1, 21/11/2011
 */
public abstract aspect SingletonProtocol {

    /**
     * stores the <i>Singleton</i> instances
     */
    private Map<Class<Object>, Object> singletonsTable = 
            new Hashtable<Class<Object>, Object>();

     /**
     * Defines the <i>Singleton</i> role. 
     */
    protected interface SingletonInterface{}

     /**
     * Placeholder for exceptions to the <i>Singleton</i>'s constructor
     * protection. For example, non-singleton subclasses may need to 
     * access the protected constructor of the <i>Singleton</i> normally.
     * 
     * An alternative implementation would be to define an interface
     * for singleton exceptions similar to the one above.
     */
    protected pointcut protectionExclusions();

    private pointcut singletonInstantiator() : call ((SingletonInterface+).new(..)) && !protectionExclusions();

    /**
     * Protects the <i>Singleton</i>'s constructor. Creates the unique
     * instance on demand and returns it instead of a new object.
     * 
     * @return the singleton instance 
     */
    @SuppressWarnings("unchecked")
    @AdviceName("newCatcher")       
    Object around() : singletonInstantiator(){
        Class<Object> singleton = thisJoinPoint.getSignature().getDeclaringType();
        if(!singletonsTable.containsKey(singleton))
            singletonsTable.put(singleton, proceed());

        return singletonsTable.get(singleton);
    }
}

And here is an example:

package singleton.aspectJ;

public aspect SingletonInstance extends SingletonProtocol{
    declare parents: God implements SingletonInterface;

    protected pointcut protectionExclusions(): 
        call((Canaanites+).new(..));  
}

In this case God is a singleton because it implements the SingletonInterface. Another class Cannnites is a child of God, but is added as an exception so it is not singleton. Quite amazingly, this is the code of God and it's child:

public class God {
    //Code specific to this class's objective
}

public class Caanites extends God {
    //Code specific to this class's objective
}

As you can see, quite amazingly, the God and Caanites class don't have any pattern code. I Hope I've help.

Flame_Phoenix
  • 16,489
  • 37
  • 131
  • 266
  • 1
    "The java language itself does not provide a good way to define the Singleton pattern IMO." Single-element enum. - Effective Java Second Edition – Aurand Jan 28 '13 at 23:15
  • Crap, guess I need to actualize myself. No worries though AspectJ is still awesome :P Thx for the post! – Flame_Phoenix Jan 29 '13 at 01:51
0

Try to get rid of a singleton, which is an anti-pattern in object oriented programming. Instead, make your objects composable and pass dependencies in constructors. This is how you solve the root cause of your problem and will always be sure that you have exactly one instance of a class.

yegor256
  • 102,010
  • 123
  • 446
  • 597