javaerror-handlingstatic-initializer

Is it appropriate to catch java.lang.ExceptionInInitializerError in multi-threaded application?


I have a class that loads and parse data from XML files in a static initializer like so:

class A {
    //static structures to store parsed XML data
    public static int num;
    ...

    static {
        try {
            //load/parse XML data
        catch (Exception e) {
            throw new RuntimeException("...");
        }
    }

    public static void method1() {
        //do some work on data
}

The data loaded by this class is used to load critical data into my application:

class Important {
    ...

    public initCriticalData() {
        try {
            Class A.method();
        catch(java.lang.ExceptionInInitializerError e) {
            //notify user of failure to load/parse XMLs and wait for user to close application
        }
    }
}

It is recommended to not catch fatal errors, but in this situation would it be appropriate to catch an error for notifying the user? Or should I have taken a different direction in my design and have loaded data outside a static initializer? Data needed to be loaded lazily, which is why I went with this approach.


Solution

  • It is only appropriate to catch this error if you are going to print an error message and then immediately terminate the application.

    The problem is that the class whose initialization has failed will be permanently stuck, as will any other class whose initialization depends on the class. This will lead to more exceptions whenever something attempts to use one of these classes.

    The only possibility of fixing this is if all of the affected classes are loaded via a child classloader ... that can be abandoned / replaced with a new one. This is possible in theory, but often impossible in practice.

    My recommendation would be NOT do the initialization in a static initializer if you anticipate that the initialization may fail due to something that the user does. Instead, do the initialization explicitly; e.g. using lazy initialization the first time that a Singleton getInstance method is called.