How can I ensure that the one-contact contract is not broken in a multi-VM environment?

According to the singleton design pattern, there is only one instance of the Singleton class in the entire "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 that the same Singleton class is loaded by multiple classloaders.

How can a developer ensure that only one instance is available in an entire multi-VM environment? Is there a way to ensure that classes are loaded through only one classloader?

+3


source to share


3 answers


Short answer? in an uncontrolled environment, you cannot. That the fallacy of the Singleton pattern is indeed impossible to achieve in a normal environment. Think about it: a class object exists in the context of a classloader, there may be several of those living in the same virtual machine. And inside the same node there can be several virtual machines. And multiple nodes can be part of the same application. Of course, each of these class objects will create one instance of the class if implemented as single ones, but there can (potentially) many class objects.



As mentioned in the comment by Oleg Mikheev, the latest versions of the Java EE specification have provisions for singleton session beans; I'm not familiar with their implementation details, but I'm left to wonder if they are really singlets: a single instance existing in a clustered application, or if it's just a logical abstraction, with multiple instances existing in different nodes.

+4


source


Well, I assume you are talking about java. The java language itself does not provide a good way to define a Singleton pattern IMO. So when I want to use certain patterns in my code, like this one, I extend it with AspectJ.

With AspectJ, you can catch every call to any constructor and make sure that you always return the same object and still have the same single, 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> 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> 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> 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's 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 single because he implements SingletonInterface. Another class, Cannnites, is a child of God, but is added as an exception, so it is not single. It's totally amazing that this is the code of God and this is a child:

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

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

      

As you can see, it is quite surprising that the God and Kaanite class does not have any template code. Hope I can help.

0


source


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

0


source







All Articles