Minborg

Minborg
Minborg

Saturday, January 31, 2015

Enforcing Java Singletons is Very Hard

Background

A singleton is a class that is instantiated exactly one time and can be used to represent "global" or system wide components. Common usages of singletons include loggers, factories, window managers or platform components. My general tip is to avoid using singletons when possible, because it is difficult to break out or override functionality and also to write test mocks and they also tend to create a bad over all code structure. As it turns out in this post, they are also insecure.

Many efforts has been made to devise good singleton patterns but there is one surprisingly easy and efficient way of doing it. However, there is really no rock solid way of guaranteeing that the singleton integrity is not breached. Read this post and see if you agree.

The Final Field Scheme

This solution relies on keeping the constructor private and exporting a public static final member to provide singleton access like this:

public class FooSingleton {

    public final static FooSingleton INSTANCE = new FooSingleton();

    private FooSingleton() { }
   
    public void bar() { }
       
}

When the class is first referenced, the static members are initialized whereby the private constructor is called only once. It is guaranteed that, even though several threads may reference the class before it has been initialized, the JVM will make sure that the class is properly initialized before the threads can continue to run. However, there is a risk that someone might create spurious instance of the class using reflection, using the setAccessible(true) method. This is how it can be done:

Constructor[] constructors = FooSingleton.class.getDeclaredConstructors();
Constructor constructor = constructors[0];
constructor.setAccessible(true);
FooSingleton spuriousFoo = (FooSingleton) constructor.newInstance(new Object[0]);
We need to modify the constructor so it protects the class from being constructed multiple times, for example by throwing an exception when it is called again. If we modify the FooSingleton like this, we protect against such attacks:

public class FooSingleton2 {

    private static boolean INSTANCE_CREATED;
    public final static FooSingleton2 INSTANCE = new FooSingleton2();

    private FooSingleton2() {
        if (INSTANCE_CREATED) {
            throw new IllegalStateException("You must only create one instance of this class");
        } else {
            INSTANCE_CREATED = true;
        }
    }

    public void bar() { }

}

Although this appears much safer, is it almost as easy as before to create undesired instances of the class. We can just pick up the INSTANCE_CREATED field and modify it before we do the same trick as before like demonstrated here under:

Field f = FooSingleton2.class.getDeclaredField("INSTANCE_CREATED");
f.setAccessible(true);
f.set(null, false);

Constructor[] constructors = FooSingleton2.class.getDeclaredConstructors();
Constructor constructor = constructors[0];
constructor.setAccessible(true);
FooSingleton2 spuriousFoo = (FooSingleton2) constructor.newInstance(new Object[0]);

This is not a viable solution because any protection we introduce may be circumvented using reflection.

The Static Factory Scheme

In this approach, the public member is a static factory like this:

public class FooSingleton3 {

    public final static FooSingleton3 INSTANCE = new FooSingleton3();

    private FooSingleton3() { }

    public static FooSingleton3 getInstance() { return INSTANCE; }

    public void bar() { }

}

When getInstance() is called, it always returns the same object reference. Even though this scheme has the same reflection vulnerability as the previous scheme, it has some advantages. For example, you can change the enforcement of the singleton without changing your actual API as you will see later in this post. Historically, a getInstance() method has been used for most singleton implementations and, by de-facto convention, it constitutes a clear marker that this really is a singleton.

The Initialization-on-demand Holder Idiom

If you want to defer the creation of the singleton as much as possible (i.e. lazy initialization), you can use the Initialization-on-demand Holder Idiom where the singleton is created in a thread safe way when the getInstance() is first called. This is an improvement over the previous schemes where the singleton is created when the class is first referenced (i.e. eager initialization). It looks like this:

public class FooSingleton4 {
  
    private FooSingleton4() {
    }
  
    public static FooSingleton4 getInstance() {
        return FooSingleton4Holder.INSTANCE;
    }
  
    private static class FooSingleton4Holder {

        private static final FooSingleton4 INSTANCE = new FooSingleton4();
    }
}

Look Out for Serializable

If the singleton implements serializable, it is exposed to another threat to its singleton property. Because of this, you need to declare all fields transient (so that they are not serialized) and provide a custom readResolve() method that just returns the INSTANCE reference.

The Enum Idiom

This scheme simply uses an Enum as the holder of the single INSTANCE member like this:

public enum FooEnumSingleton {

    INSTANCE;

    public static FooEnumSingleton getInstance() { return INSTANCE; }

    public void bar() { }

}

According to the Java Language Specification §8.9 "The final clone method in Enum ensures that enum constants can never be cloned, and the special treatment by the serialization mechanism ensures that duplicate instances are never created as a result of deserialization. Reflective instantiation of enum types is prohibited. Together, these four things ensure that no instances of an enum type exist beyond those defined by the enum constants."

Thus, we allegedly get protection against serialization, clone and reflection attacks for free. When I first saw this statement, I immediately felt compelled to prove it wrong. As you can see in the following code snippet, it was fairly easy to get around the protection.

 Constructor con = FooEnumSingleton.class.getDeclaredConstructors()[0];
 Method[] methods = con.getClass().getDeclaredMethods();
 for (Method method : methods) {
     if (method.getName().equals("acquireConstructorAccessor")) {
         method.setAccessible(true);
         method.invoke(con, new Object[0]);
     }
  }
  Field[] fields = con.getClass().getDeclaredFields();
  Object ca = null;
  for (Field field : fields) {
      if (field.getName().equals("constructorAccessor")) {
          field.setAccessible(true);
          ca = field.get(con);
      }
  }
  Method method = ca.getClass().getMethod("newInstance", new Class[]{Object[].class});
  method.setAccessible(true);
  FooEnumSingleton spuriousEnum = (FooEnumSingleton) method.invoke(ca, new Object[]{new Object[]{"SPURIOUS_INSTANCE", 1}});
  printInfo(FooEnumSingleton.INSTANCE);
  printInfo(spuriousEnum);
}

private static void printInfo(FooEnumSingleton e) {
    System.out.println(e.getClass() + ":" + e.name() + ":" + e.ordinal());
}
When we run the code, we get the following output:
class com.blogspot.minborgsjavapot.singleton.FooEnumSingleton:INSTANCE:0
class com.blogspot.minborgsjavapot.singleton.FooEnumSingleton:SPURIOUS_INSTANCE:1

A disadvantage with the Enum scheme is that we can not inherit from another base class, because enums can not extend another class. The reason for that is that it already inherently extends java.lang.Enum. If you want to mimic inheritance, you might want to consider the interface mixin pattern as described in my previous post here.

An advantage with the enum scheme is that, if you later decide to have "dualtons" or "tringletons", it is very easy to add those just by adding new enums. For example, if you have a singleton cache, you might later decide to introduce several layers of the cache.

Conclusions

All though it is difficult to circumvent some of the singleton property protections shown here, there is no really bullet prof singleton scheme around. If you can think of a better one, please feel free to drop a comment on this post!

An Enum provides a good and simple vehicle for singletons. The Initialization-on-demand holder idiom provides a good pattern if you want to use inheritance and/or want lazy initialization.

Good luck with your singletons!

4 comments:

  1. I develop a match making website clone in java platform and i am stuck over in some problem . So i need a suggestion of java clone.

    ReplyDelete
  2. but why would you want to? I prefer my lifecycle management to remain squarely the domain of something that specializes in it, like a dependency injection container.

    ReplyDelete
    Replies
    1. I agree with you. You should not use singletons. Perhaps I will write an article about other lifecycle schemes in the futute.

      Delete
  3. Hi Miniborg,
    You may find this implementation of singleton interesting. Using a classloader we can lock singleton's a bit more. I posted the code on my website:

    http://jnetpcap.com/?q=node/1328

    ReplyDelete