Singleton pattern, multiple instances?

I was recently asked the following trivia concerning the Singleton Pattern:

The following class implements the Singleton pattern. The basic idea is to ensure that there will only exist ONE instance of the Dog class.

publicclass Dog{

publicstaticfinal Dog INSTANCE =new Dog();

private Dog(){}

@Override

public String toString(){

return"Gua Gua!";

}

}

However, it is posible in Java to create a second instance from another class. Write the code that may accomplish this.

There's also another condition: the use ofreflection is not allowed, so that it's not possible anymore to use something like this:

Dog d = (Dog)java.security.AccessController.doPrivileged(

new PrivilegedAction()

and then:

Constructor cons= Dog.class.getDeclaredConstructor();

cons.setAccessible(true);

return cons.newInstance(null);

I have read a lot about the drawbacks of the Singleton pattern and most of them consist on Thread issues (which I think by declaring as a class variable the unique INSTANCE and by avoiding the typicalgetInstance() method are discarded) and Class loading.

Any help with this challenge?

[1858 byte] By [cobi3000a] at [2007-10-2 3:56:19]
# 1
> I was recently asked the following trivia concerning> the Singleton Pattern:"I was recently given a homework problem concerning the Singleton Pattern:"Look at serialization.
es5f2000a at 2007-7-15 23:17:40 > top of Java-index,Other Topics,Patterns & OO Design...
# 2

Very easy, override the readResolve() method and make the class Serializable.

If your Singleton is read-only, then thread safety is not an issue. Singletons (and caching strategies) are best when used on read-only or read-mostly data. This is because they behave as a proxy for global variables. Synchronizing the methods is an option, but in a multi-threaded environment, this could lead to a scaling bottleneck.

I do not see the issue with using getInstance(). Assuming there is not a race condition where null is being checked (e.g., initializing the instance as was done in your case or via a static initializer). Class loading should not be an issue either. Garbage collection might be, but I do not see how class loading would be any different. Though I may be wrong on that one.

- Saish

Saisha at 2007-7-15 23:17:40 > top of Java-index,Other Topics,Patterns & OO Design...
# 3
I didn't know the serialize one.1. Do it via JNI.2. Do it with two class loader instances.Did it mention that it has to be in the same VM? If not then just run two VMs.
jschella at 2007-7-15 23:17:40 > top of Java-index,Other Topics,Patterns & OO Design...
# 4
Of course one could also mention that the whole point of a singleton is that there is one and so if someone wants more than one then they should change the design rather than trying to find code loop holes around it.Perhaps a multiton would work.
jschella at 2007-7-15 23:17:40 > top of Java-index,Other Topics,Patterns & OO Design...
# 5

> Very easy, override the readResolve() method and make

> the class Serializable.

Thanks for your interest in this topic. Of course, serialization is one possibility but, unfortunately, it is not possible to modify in any way the original Dog class.

I know that this "trivia" may not represent an issue that has to do with the correct use of the Singleton pattern in practice, but it has to do with the theoretical and possible drawbacks that may occur in Java.

cobi3000a at 2007-7-15 23:17:40 > top of Java-index,Other Topics,Patterns & OO Design...
# 6

> I didn't know the serialize one.

>

> 1. Do it via JNI.

> 2. Do it with two class loader instances.

>

> Did it mention that it has to be in the same VM? If

> not then just run two VMs.

I think I may have demonstrated the possibility of using two class loaders, but I haven't been able to avoid the use of Reflection which is one condition (along with the "running in the same VM", sorry not to mention that). See the code below:

import java.io.File;

import java.lang.reflect.Field;

import java.net.URL;

import java.net.URLClassLoader;

import java.util.logging.Logger;

public class Clone

{

public static void main(String args[])

throws Exception

{

// class name

String className = "Dog";

// directory that has the Dog.class file to tell the second Class Loader where to search for the class

String dir = "C:\\temp";

// Logging mechanism

Logger _logger = Logger.getLogger(Clone.class.getName());

// Instance1 get directly from the INSTANCE field variable of the Dog class

Dog dog1 = Dog.INSTANCE;

_logger.info("Loaded " + dog1.getClass().getName() + " [" + dog1.getClass().hashCode()

+ "]");

_logger.info("Instance " + dog1 + " [" + dog1.hashCode()

+ "]");

// Instance 1 misma a la anterior

Dog dog2 = Dog.INSTANCE;

_logger.info("Misma Instance " + dog2 + " [" + dog2.hashCode()

+ "]");

// Creating a second Class loader

ClassLoader classLoader2 = new URLClassLoader(

new URL[] { new File(dir).toURL() });

// we load the class

Class dogClass = classLoader2.loadClass(className);

_logger.info("Loaded " + dogClass.getName() + " [" + dogClass.hashCode()

+ "]");

// Getting the INSTANCE field that has the unique instance of the Dog Class

Field getter = dogClass.getDeclaredField("INSTANCE");

Object obj = new Object[0];

// Getting the value of the INSTANCE field

Dog dog3 = (Dog)getter.get(obj);

// We got a new Dog instance

_logger.info("Instance " + dog3 + " [" + dog3.hashCode()

+ "]");

}

}

However I still have my doubts if this correctly do the trick in showing the Class Loading drawback of a Singleton.

cobi3000a at 2007-7-15 23:17:40 > top of Java-index,Other Topics,Patterns & OO Design...
# 7
Sure, you can use two classloaders, but (if you want to be picky) the "Dog" classes they load are not the same class, even though they were loaded from the same place. So you only create one instance of each of the two different "Dog" classes.
DrClapa at 2007-7-15 23:17:40 > top of Java-index,Other Topics,Patterns & OO Design...
# 8

If you make the class Serializable, the following code does work:

public class Singleton implements Serializable {

private static final Singleton INSTANCE = new Singleton();

private Singleton() {

}

public static final Singleton getInstance() {

return INSTANCE;

}

static final public void main(final String[] args)

throws Exception {

Singleton first = Singleton.getInstance();

ByteArrayOutputStream byteOut = new ByteArrayOutputStream();

ObjectOutputStream objectOut = new ObjectOutputStream(byteOut);

objectOut.writeObject(first);

ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());

ObjectInputStream objectIn = new ObjectInputStream(byteIn);

Singleton second = (Singleton) objectIn.readObject();

System.out.println(first == second);

}

}

Though if you cannot make the class Serializable and you cannot use reflection, I'm not sure what else you could do.

- Saish

Saisha at 2007-7-15 23:17:40 > top of Java-index,Other Topics,Patterns & OO Design...
# 9

緿oes it make any difference in all the possible solutions you all have suggested if the Singleton class is declared as a subclass of Exception?

public class Dog extends Exception{

public static final Dog INSTANCE = new Dog();

private Dog() {}

@Override

public String toString() {

return "Gua Gua!";

}

}

That was the last update to the trivia I proposed (AN ERRATA).

Thanks in advance for any suggestion.

cobi3000a at 2007-7-15 23:17:40 > top of Java-index,Other Topics,Patterns & OO Design...
# 10
> 緿oes it make any difference in all the possible> solutions you all have suggested if the Singleton> class is declared as a subclass of Exception?> Yes it does, because Exception implements Serializable, so Dog is all of a sudden Serializable.
happy_hippoa at 2007-7-15 23:17:40 > top of Java-index,Other Topics,Patterns & OO Design...
# 11

I would like to thank you. Your answer was the correct one. There was an omission (not of my own) on the original specification of the trivia. My last post states the Errata made, which implies that the singleton class extends from the Exception class, and as Exception implements the serializable interface, this solution is completely possible to demonstrate that there exist two instances.

cobi3000a at 2007-7-15 23:17:40 > top of Java-index,Other Topics,Patterns & OO Design...
# 12
So, es5f2000's very first reply was the correct one. :^)- Saish
Saisha at 2007-7-15 23:17:40 > top of Java-index,Other Topics,Patterns & OO Design...
# 13

> I would like to thank you. Your answer was the

> correct one.

Except that one of course must add....

However anyone that actually writes code like this should be fired or treated as a junior programmer because writing code like this totally disregards the nature of software engineering versus that of just understanding what is possible in a language.

And of course no serious engineer need know this except to be able to recognize when another 'developer' is writing code that is not maintainable.

jschella at 2007-7-15 23:17:40 > top of Java-index,Other Topics,Patterns & OO Design...