ExceptionInInitializerError是Java中一个比较特殊的错误,它不属于Exception的子类,而是Error的直接子类,通常和类的静态初始化过程相关。很多开发者遇到这个错误时,第一反应会去查业务代码的逻辑,却很容易忽略静态初始化阶段的问题。下面我们结合具体场景来梳理它的出现原因。

静态代码块中抛出未捕获的异常
当类被加载时,JVM会执行静态代码块中的逻辑,如果静态代码块中抛出了任何异常,且没有在代码块内部捕获处理,就会触发ExceptionInInitializerError。我们可以通过下面的示例代码来复现这个场景:
public class StaticBlockErrorDemo {
// 静态代码块中主动抛出运行时异常
static {
System.out.println("执行静态代码块逻辑");
throw new RuntimeException("静态代码块内部发生异常");
}
public static void main(String[] args) {
// 初始化类的时候触发静态代码块执行,进而抛出错误
StaticBlockErrorDemo demo = new StaticBlockErrorDemo();
}
}运行上面的代码,控制台会输出ExceptionInInitializerError,并且错误的原因就是静态代码块中抛出的RuntimeException。这里的异常会被JVM包装成ExceptionInInitializerError抛出,我们可以通过这个错误的getCause()方法获取到原始的异常信息。
静态变量初始化时抛出异常
静态变量的初始化赋值逻辑,本质上也是在类加载的静态初始化阶段执行的,和静态代码块的执行时机一致。如果静态变量的初始化过程中调用的方法抛出了未捕获的异常,同样会触发ExceptionInInitializerError。
public class StaticVarErrorDemo {
// 静态变量初始化时调用方法,方法内部抛出异常
private static int count = initCount();
private static int initCount() {
System.out.println("初始化静态变量count");
// 模拟初始化时的异常场景
if (true) {
throw new IllegalArgumentException("静态变量初始化失败");
}
return 10;
}
public static void main(String[] args) {
// 访问静态变量触发类初始化,进而抛出错误
System.out.println(StaticVarErrorDemo.count);
}
}这个场景中,count是静态变量,初始化时调用了initCount方法,方法抛出了IllegalArgumentException,没有被捕获,所以JVM会抛出ExceptionInInitializerError,我们可以在错误信息中看到原始的IllegalArgumentException作为原因。
静态初始化过程中的异常被包装传播
有时候静态初始化阶段抛出的异常可能不是直接未捕获,而是被后续的静态初始化逻辑再次包装,这种情况下最终抛出的还是ExceptionInInitializerError。比如静态代码块中调用的方法抛出了异常,静态代码块没有捕获,就会触发这个错误。
public class WrappedErrorDemo {
static {
try {
// 调用会抛出异常的方法
riskMethod();
} catch (Exception e) {
// 这里只打印了异常,没有重新抛出或者处理,但是静态代码块后续的异常还是会触发错误
e.printStackTrace();
}
// 静态代码块后续还有可能抛出其他异常,最终还是会导致初始化失败
throw new NullPointerException("静态代码块后续异常");
}
private static void riskMethod() {
throw new RuntimeException("风险方法异常");
}
public static void main(String[] args) {
new WrappedErrorDemo();
}
}这种情况下,最终抛出的ExceptionInInitializerError的原因就是NullPointerException,而之前riskMethod抛出的异常只会被打印,不会影响最终的错误类型,因为静态初始化阶段只要有一个未处理的异常,就会触发这个错误。
如何排查和解决这类问题
遇到ExceptionInInitializerError的时候,可以按照下面的步骤排查:
- 首先查看错误栈信息,找到
ExceptionInInitializerError的cause,也就是原始抛出的异常,这是定位问题的关键。 - 检查对应类的静态代码块和静态变量的初始化逻辑,看是否有未处理的异常抛出。
- 在静态初始化逻辑中,对可能抛出异常的操作加上try-catch处理,或者在初始化时做好参数校验,避免异常抛出。
需要注意的是,ExceptionInInitializerError是Error级别的,一般不建议在代码中捕获这类错误,而是应该从根源上修复静态初始化阶段的逻辑问题,避免异常抛出。
ExceptionInInitializerErrorJava静态初始化静态变量静态代码块异常传播修改时间:2026-05-25 21:48:29