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:
- A synchronized block is needed, where static initializers are inherently very thread-safe
- It incurs an additional expense in methods that will be using these fields
- 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
}
}