Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
bgColor#FFcccc
class MySingleton {
  private static MySingleton Instanceinstance;

  protected MySingleton() {    
    Instanceinstance = new MySingleton();
  }

  public static synchronized MySingleton getInstance() {    
    return Instanceinstance;
  }
}

A malicious subclass may extend the accessibility of the constructor from protected to public, allowing untrusted code to create multiple instances of the singleton. Also, the class field Instance has not been declared final.

...

Code Block
bgColor#ccccff
class MySingleton {
  private static final MySingleton Instanceinstance = new MySingleton();

  private MySingleton() {    
    // private constructor prevents instantiation by untrusted callers
  }

  public static synchronized MySingleton getInstance() {    
    return Instanceinstance;
  }
}

The MySingleton class need not be declared final because it has a private constructor.

...

Code Block
bgColor#FFcccc
class MySingleton {
  private static MySingleton Instanceinstance;

  private MySingleton() {    
    // private constructor prevents instantiation by untrusted callers
  }

  // Lazy initialization
  public static MySingleton getInstance() { // Not synchronized
    if (Instanceinstance == null) {
      Instanceinstance = new MySingleton();
    }
    return Instanceinstance;
  }
}

A singleton initializer method in a multithreaded program must employ some form of locking to prevent construction of multiple singleton objects.

...

Code Block
bgColor#FFcccc
public static MySingleton getInstance() {
  if (Instanceinstance == null) {
    synchronized (MySingleton.class) {
      Instanceinstance = new MySingleton();
    }
  }
  return Instanceinstance;
}

This is because two or more threads may simultaneously see the field Instance instance as null in the if condition and enter the synchronized block one at a time.

...

Code Block
bgColor#ccccff
class MySingleton {
  private static MySingleton Instanceinstance;

  private MySingleton() {
    // private constructor prevents instantiation by untrusted callers
  }

  // Lazy initialization
  public static synchronized MySingleton getInstance() {
    if (Instanceinstance == null) {
      Instanceinstance = new MySingleton();
    }
    return Instanceinstance;
  }
}

Compliant Solution (Double-Checked Locking)

...

Code Block
bgColor#ccccff
class MySingleton {
  private static volatile MySingleton Instanceinstance;

  private MySingleton() {
    // private constructor prevents instantiation by untrusted callers
  }

  // Double-checked locking
  public static MySingleton getInstance() {
    if (Instanceinstance == null) {
      synchronized (MySingleton.class) {
        if (Instanceinstance == null) {
          Instanceinstance = new MySingleton();
        }
      }
    }
    return Instanceinstance;
  }
}

This design pattern is often implemented incorrectly. Refer to rule LCK10-J. Do not use incorrect forms of the double-checked locking idiom for more details on the correct use of the double-checked locking idiom.

...

Code Block
bgColor#ccccff
class MySingleton {
  static class SingletonHolder {
    static MySingleton Instanceinstance = new MySingleton();
  }

  public static MySingleton getInstance() {
    return SingletonHolder.Instanceinstance;
  }
}

This is known as the initialize-on-demand holder class idiom. Refer to rule LCK10-J. Do not use incorrect forms of the double-checked locking idiom for more information.

...

Code Block
bgColor#FFcccc
class MySingleton implements Serializable {
  private static final long serialVersionUID = 6825273283542226860L;
  private static MySingleton Instanceinstance;

  private MySingleton() {
    // private constructor prevents instantiation by untrusted callers
  }

  // Lazy initialization
  public static synchronized MySingleton getInstance() {
    if (Instanceinstance == null) {
      Instanceinstance = new MySingleton();
    }
    return Instanceinstance;
  }
}

A singleton's constructor cannot install checks to enforce the requirement that the class is only instantiated once because deserialization can bypass the object's constructor.

...

Code Block
bgColor#FFcccc
class MySingleton implements Serializable {
  private static final long serialVersionUID = 6825273283542226860L;
  private static MySingleton Instanceinstance;

  private MySingleton() {
    // private constructor prevents instantiation by untrusted callers
  }

  // Lazy initialization
  public static synchronized MySingleton getInstance() {
    if (Instanceinstance == null) {
      Instanceinstance = new MySingleton();
    }
    return Instanceinstance;
  }

  private Object readResolve() {
    return Instanceinstance; 
  }
}

At runtime, an attacker can add a class that reads in a crafted serialized stream:

...

Upon deserialization, the field MySingleton.untrusted is reconstructed before MySingleton.readResolve() is called. Consequently, Untrusted.captured is assigned the deserialized instance of the crafted stream instead of MySingleton.Instanceinstance. This issue is pernicious when an attacker can add classes to exploit the singleton guarantee of an existing serializable class.

...

Code Block
bgColor#FFcccc
class MySingleton implements Serializable {
  private static final long serialVersionUID =
      2787342337386756967L;
  private static MySingleton Instanceinstance;
  
  // non-transient instance field 
  private String[] str = {"one", "two", "three"}; 
                 
  private MySingleton() {
    // private constructor prevents instantiation by untrusted callers
  }

  public void displayStr() {
    System.out.println(Arrays.toString(str));
  }
 
  private Object readResolve() {
    return Instanceinstance;
  }
}

"If a singleton contains a nontransient object reference field, the contents of this field will be deserialized before the singleton’s readResolve method is run. This allows a carefully crafted stream to 'steal' a reference to the originally deserialized singleton at the time the contents of the object reference field are deserialized" [Bloch 2008].

...

Code Block
bgColor#ccccff
public enum MySingleton {
  ; // empty list of enum values

  private static MySingleton Instanceinstance;

  // non-transient field
  private String[] str = {"one", "two", "three"};

  public void displayStr() {
    System.out.println(Arrays.toString(str));
  }	 
}

...

Code Block
bgColor#FFcccc
class MySingleton implements Cloneable {
  private static MySingleton Instanceinstance;

  private MySingleton() {
    // private constructor prevents
    // instantiation by untrusted callers
  }

  // Lazy initialization
  public static synchronized MySingleton getInstance() {
    if (Instanceinstance == null) {
      Instanceinstance = new MySingleton();
    }
    return Instanceinstance;
  }
}

Compliant Solution (Override clone() Method)

...

Code Block
bgColor#ccccff
class MySingleton implements Cloneable {
  private static MySingleton Instanceinstance;

  private MySingleton() {
    // private constructor prevents instantiation by untrusted callers
  }

  // Lazy initialization
  public static synchronized MySingleton getInstance() {
    if (Instanceinstance == null) {
      Instanceinstance = new MySingleton();
    }
    return Instanceinstance;
  }

  public Object clone() throws CloneNotSupportedException {
    throw new CloneNotSupportedException();
  }
}

...