Exceptions and static initializers

A common problem in Java is Exceptions in static initializers. What on earth do you do with them? This has been discussed a bit on my local JUG recently, and here’s a bit of a summary.

Common solutions:

  • Wrap the Exception in an ExceptionInInitializerError and re-throw it
    • This causes the entire class to be marked as “errored”, as though it didn’t validate
    • Any further use of the class will result in a NoClassDefFoundException, which can be confusing
  • Log the Exception and continue as normal
    • If the log levels are set to high, nobody will ever see the Exception
    • Some Loggers get configured to drop stack traces
    • Sometimes the normal execution of code should stop
      • Someone configured something badly
      • The database is not running
  • Both of the above is a common pattern as well, and is generally considered “best practice”

One solution mentioned is to lazy-instantiate the static fields in the class. This is a nice idea, but has a few flaws:

  1. A synchronized block is needed, where static initializers are inherently very thread-safe
  2. It incurs an additional expense in methods that will be using these fields
  3. In the case of a singleton, it’s likely that the first method that will be called will cause the “lazy” code to run. Since classes are generally lazy-instantiated by the VM, a static initializer would achieve the same thing.

My solution was this one:

public class StaticInitializerExample {
 private static final Wrapper WRAPPER = createWrapper();

 private static abstract class Wrapper {
  private abstract StaticInitializerExample get();
 }

 private static Wrapper createWrapper() {
  try {
   final StaticInitializerExample c =
     new StaticInitializerExample();

   return new Wrapper() {
    public StaticInitializerExample get() {
     return c;
    }
   };
  } catch(final Exception e) {
    return new Wrapper() {
     public StaticInitializerExample get() {
      throw new RuntimeException(e);
     }
    };
  }
 }

 public static StaticInitializerExample getInstance() {
  return WRAPPER.get();
 }

 private StaticInitializerExample() throws Exception {
  // do code that could throw an exception
 }
}
Advertisements

One Response to “Exceptions and static initializers”

  1. Ole V. Villumsen Says:

    Yes, it a common problem. “Log and continue as normal” — I agree it’s common, but I certainly consider it bad practice still. It may easily give you all kinds of problems and confusion further down the road.
    Also throwing an error (like ExceptionInInitializerError) may be too hard. It’s good practice not to catch errors, so this will probably terminate the program. I wanted to leave to the caller to decide whether the program could still do useful work even if one class failed to be statically initialized.
    Here’s what I did:

    public class MyDao {

    private static final Logger log = new Logger(MyDao.class);

    /**
    * Should be null; if non-null it signals an error during static initialization
    * that in turn means that the class is in an unusable state and that no objects should be created
    */
    private static String staticInitErrorMsg;

    static {
    try {
    Class.forName(“COM.ibm.db2os390.sqlj.jdbc.DB2SQLJDriver”);
    staticInitErrorMsg = null;
    } catch (ClassNotFoundException e) {
    staticInitErrorMsg = e.toString();
    log.error(“MyDao static initializer: ” + staticInitErrorMsg, e);
    }
    }

    public MyDao() {
    if (staticInitErrorMsg != null) {
    throw new IllegalStateException(“MyDao class not initialized: ” + staticInitErrorMsg);
    }
    }

    // methods here

    }

    (I am using a log4j-like framework; you can log the error and/or the stack trace some other way if you prefer)
    I ought to document that the constructor may throw IllegalStateException and under what circumstances; other than that I think I’ve obtained what I wanted. Copy if you like it. 🙂


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: