Blog |

How to Handle the Exception In Initializer Runtime Error in Java

How to Handle the Exception In Initializer Runtime Error in Java
Table of Contents

Introduction to Runtime Errors & Exceptions

Unlike compile-time errors which are detected during compilation [1], runtime errors occur during program execution, i.e. runtime. Java’s runtime error hierarchy is somewhat complicated compared to other programming languages, but at the basic level there are two main categories: runtime errors and runtime exceptions, the latter of which being further divided into checked and unchecked exceptions (see Figure 1 below). Unchecked exceptions are also lumped into the somewhat confusingly named RuntimeException superclass, while all runtime errors are also considered to be unchecked. The term “unchecked” refers to errors and exceptions that Java doesn’t require to be caught or otherwise specified in the code [2]. Runtime Java errors and exceptions are otherwise jointly referred to as throwables, as per the name of the Throwable class—the parent class of all errors and exceptions in this language [3].

Java runtime and exceptions hierarchy
Figure 1. Java runtime errors & exceptions hierarchy [4]

 

ExceptionInInitializerError Error: What, Why & How?

After successfully compiling a program, the Java Virtual Machine (JVM) performs dynamic loading, linking, and initializing of classes and interfaces, broadly known as the class loading process [5]. This process includes the evaluation of all static initializer blocks and variable assignments present in the compiled code. If, during this evaluation, any unexpected exception occurs, the JVM throws an ExceptionInInitializerError runtime error, points to the specific exception that caused the error, and subsequently exits the program.

The ExceptionInInitializerError error occurs every time there is an unchecked (and uncaught) exception taking place inside a static initializer or a static variable assignment. The JVM wraps this exception inside an instance of the java.lang.ExceptionInInitializerError class (which itself is a subclass of the more generic java.lang.LinkageError class of errors [6]) and maintains a reference to it as the root cause.

 

How to handle the ExceptionInInitializerError Error

To avoid this error, simply ensure that:

  • static initializers of classes do not throw any unchecked exception, and that
  • static class variable initializations do not throw any unchecked exceptions.

 

ExceptionInInitializerError Error Examples

Unchecked exception during static variable initialization

Figure 2(a) shows how an unchecked exception such as an instance of the java.lang.ArithmeticException triggers the ExceptionInInitializerError error. The error message denotes the division by zero arithmetic exception as the cause for the error and points to the specific class and line of code where it happened. Eradicating this arithmetic error, as shown in Figure 2(b), solves the issue.

(a)

1
2
3
4
5
6
7
8
9
package rollbar;

public class EIIE {
    private static int x = 20 / 0;

    public static void main(String... args) {
        System.out.println(x);
    }
}
Exception in thread "main" java.lang.ExceptionInInitializerError
Caused by: java.lang.ArithmeticException: / by zero
    at rollbar.EIIE.<clinit>(EIIE.java:4)

(b)

1
2
3
4
5
6
7
8
9
package rollbar;

public class EIIE {
    private static int x = 20 / 10;

    public static void main(String... args) {
        System.out.println(x);
    }
}
2

Figure 2: ExceptionInInitializerError error with static variable assignment (a) error and (b) resolution

 

Unchecked exception inside static initializer

Having an unchecked exception thrown inside a static initializer will inevitably trigger the ExceptionInInitializerError runtime error. Figure 3(a) shows how invoking the String::length method on a non-initialized String variable (whose value defaults to null) throws the NullPointerException, which in turn triggers the ExceptionInInitializerError error, because the exception occurred inside the static initializer of the class. To handle this type of scenario, one can implement a simple null guard (Figure 3(b)), or use a try-catch block to explicitly catch and handle the exception (Figure 3(c)). Note that these approaches assume that there is no logical error in the rest of the code, and that the desired functionality is correctly implemented.

(a)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package rollbar;

public class EIIE2 {
    private static String str;
    private static long len;

    static {
        len = str.length();
    }

    public static void main(String... args) {
        System.out.println("String: " + str);
        System.out.println("Length: " + len);
    }
}
Exception in thread "main" java.lang.ExceptionInInitializerError
Caused by: java.lang.NullPointerException: Cannot invoke "String.length()" because "rollbar.EIIE2.str" is null
    at rollbar.EIIE2.<clinit>(EIIE2.java:8)

(b)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package rollbar;

public class EIIE2 {
    private static String str;
    private static long len;

    static {
        len = str == null ? -1 : str.length();
    }

    public static void main(String... args) {
        System.out.println("String: " + str);
        System.out.println("Length: " + len);
    }
}
String: null
Length: -1

(c)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package rollbar;

public class EIIE2 {
    private static String str;
    private static long len;

    static {
        try {
            len = str.length();
        } catch (NullPointerException e) {
            len = -1;
        }
    }

    public static void main(String... args) {
        System.out.println("String: " + str);
        System.out.println("Length: " + len);
    }
}
String: null
Length: -1

Figure 3: ExceptionInInitializerError error inside static initializer (a) error and (b)(c) two possible resolutions

 

Checked exception inside static initializer?

Since it is impossible to throw checked exceptions from a static block (this is not allowed and will result in a compile-time error), it is good practice to wrap them inside an ExceptionInInitializerError instance manually, as shown in Figure 4. This is a clean way of handling checked exceptions in static initializers where their use is warranted, and it stays true to the design principles of the language. For completeness, if the checked exception in question doesn’t get thrown, the ExceptionInInitializerError isn’t thrown either and the code executes normally (Figure 4(b)).

(a)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package rollbar;

import java.lang.reflect.Field;

public class EIIE3 {
    private static Field fieldInfo;

    static {
        try {
            fieldInfo = EIIE3.class.getDeclaredField("x");
        } catch (NoSuchFieldException e) {
            throw new ExceptionInInitializerError(e);
        }
    }

    public static void main(String... args) {
        System.out.println(fieldInfo.getName());
        System.out.println(fieldInfo.getType());
    }
}
Exception in thread "main" java.lang.ExceptionInInitializerError
    at rollbar.EIIE3.<clinit>(EIIE3.java:12)
Caused by: java.lang.NoSuchFieldException: x
    at java.base/java.lang.Class.getDeclaredField(Class.java:2569)
    at rollbar.EIIE3.<clinit>(EIIE3.java:10)

(b)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package rollbar;

import java.lang.reflect.Field;

public class EIIE3 {
    private static Field fieldInfo;

    static {
        try {
            fieldInfo = EIIE3.class.getDeclaredField("x");
        } catch (NoSuchFieldException e) {
            throw new ExceptionInInitializerError(e);
        }
    }

    private static double x;

    public static void main(String... args) {
        System.out.println(fieldInfo.getName());
        System.out.println(fieldInfo.getType());
    }
}
x
double

Figure 4: ExceptionInInitializerError thrown manually inside a static initializer

 

Conclusion

Runtime errors occur during the execution of a program and as such are more difficult to prevent than compile-time errors. In Java, some of these errors are triggered during the class loading process, or in colloquial terms, when the program is starting up. This allows for a certain category of errors to be detected at a very early stage, despite the program having been successfully compiled. One such error is the ExceptionInInitializerError error which signals that an unexpected exception has occurred during the evaluation of a static initializer or the initialization of a static variable. This error serves as a runtime wrapper for the underlying exception and halts the JVM until the underlying exception is resolved.

 

Track, Analyze and Manage Errors With Rollbar

Managing Java errors and exceptions in your code is challenging. It can make deploying production code an unnerving experience. Being able to track, analyze, and manage errors in real-time can help you to proceed with more confidence. Rollbar automates error monitoring and triaging, making fixing Java errors easier than ever. Sign Up Today!

 

References

[1] Rollbar, 2021. How to Fix "Illegal Start of Expression" in Java. Rollbar Editorial Team. [Online]. Available: https://rollbar.com/blog/how-to-fix-illegal-start-of-expression-in-java/. [Accessed Jan. 7, 2022]

[2] Oracle, 2021. Unchecked Exceptions — The Controversy (The Java™ Tutorials > Essential Java Classes > Exceptions). Oracle and/or its affiliates. [Online]. Available: https://docs.oracle.com/javase/tutorial/essential/exceptions/runtime.html. [Accessed Jan. 7, 2022]

[3] Oracle, 2021. Throwable (Java SE 17 & JDK 17). Oracle and/or its affiliates. [Online]. Available: https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Throwable.html. [Accessed Jan. 7, 2022]

[4] M. Sanger, 2018. Java Exception Hierarchy. Manish Sanger. [Online]. Available: https://www.manishsanger.com/java-exception-hierarchy/. [Accessed Jan. 7, 2022]

[5] Oracle, 2021. Chapter 5. Loading, Linking, and Initializing. Oracle Corporation and/or its affiliates. [Online]. Available: https://docs.oracle.com/javase/specs/jvms/se17/html/jvms-5.html. [Accessed Jan. 7, 2022]

[6] Oracle, 2021. LinkageError (Java SE 17 & JDK 17). Oracle and/or its affiliates. [Online]. Available: https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/LinkageError.html. [Accessed Jan. 7, 2022]

Related Posts

See all posts

"Rollbar allows us to go from alerting to impact analysis and resolution in a matter of minutes. Without it we would be flying blind."

Start continuously improving your code today.

Get Started Shape