Coders trying to implement and test the Singleton pattern (see Resources) in Java 1.1 often complained that their singleton classes were getting garbage collected; that is, the runtime unloaded the classes right out from under them! Fortunately, the upcoming Java 1.2 specification clarifies the rules for loading and unloading classes, making writing singletons much simpler.
This tip explores implementing singletons in Java and describes what we need to do to make them work in the various versions of Java floating around.
A singleton is a class for which only one instance can exist within a program. In other words, only one, single object of that particular class can be created in a program.
Here's a simple, quick-and-dirty singleton class:
public class SimpleSingleton
{
// Create the single instance, make it available statically, and
// don't let it be redefined.
private static final SimpleSingleton instance = new SimpleSingleton();
// Allow subclasses to override the constructor, if necessary.
protected SimpleSingleton()
{
// Whatever...
}
// Accessor only.
public static SimpleSingleton getInstance()
{
return instance;
}
// Methods on the object to actually do something useful.
public void doSomething()
{
// Whatever.
}
}
All we ever need to do to actually use the various methods of the SimpleSingleton class is to access the static instance member and use it to invoke our method of choice, like this:
SimpleSingleton.getInstance().doSomething();
With such a class, we never need to create and store the SimpleSingleton instance object anywhere, or worry about passing the object reference around.
All Java specifications require us to keep a reference to the singleton object, or lose it to the garbage collector. But,
in pre-1.2 Java specifications, the garbage collector was not only free to collect the singleton object but also the SimpleSingleton class!. This garbage collection of an actual class is also known as "class unloading."
Actually, in Java 1.0.x class unloading wasn't implemented, so our SimpleSingleton implementation would work just fine. Unfortunately, in Java 1.1.x even system classes were allowed to be unloaded. Typical workarounds for this inadvertent unloading of the singleton class include:
main() method (or the run() method for thread classes).main() method (or the run() method of a thread class).
Although these techniques work, they are problematic if you use third-party libraries and can't get to the singleton (as that particular class might be an internal helper class).