java.lang.ExceptionInInitializerError异常分析
今天在项目开发时遇到一个问题,整个项目是使用Spring等框架搭建起来的在运行项目时不报任何的异常信息,就是找不到某个类信息,各方查找该类确实是存在的,最后通过断点跟踪时在异常栈内发现java.lang.ExceptionInInitializerError这个异常信息,但这个异常信息没有在控制台或者日志系统中抛出来,查明原因之后就对症下药最终解决了该问题。查找该问题也着实费了一翻功夫,正好趁此机会把该问题引发的原因及针对这类问题应该如何来避免记录一下。由于该项目中的代码比较复杂,这里举一个简单的例子来说明一下该异常产生的原因。
java.lang.ExceptionInInitializerError
该异常在Java中的继承关系如下:
下面是jdk对该异常的描述
public class ExceptionInInitializerError
extends LinkageError
静态初始化程序中发生意外异常的信号。抛出 ExceptionInInitializerError
表明在计算静态初始值或静态变量的初始值期间发生异常。
从版本 1.4 开始,这个异常已经更新过,符合通用异常链机制。“保存的 throwable 对象”可能是在构造的时候提供的,并且可以通过 getException()
方法来访问,这类对象目前被认为是导致异常的原因,可以通过 Throwable.getCause()
方法以及前面提到的“遗留方法”访问它。
要理解这个异常还得从Java类中的静态变量初始化过程说起,在Java类中静态变量的初始化顺序和静态变量的声明顺序是一致的。为了验证该说法,我们写一个简单的小程序,代码如下:
-
/**
-
*
-
*/
-
package com.mhy.oo.statics;
-
-
import java.util.ArrayList;
-
import java.util.List;
-
-
/**
-
* @author mhy2011@163.com
-
* @date 2011-11-18
-
*/
-
public class StaticParams {
-
-
private static int NUM_A = getA();
-
private static int NUM_B = getB();
-
private static List<String> LIST_A = getListA();
-
-
private StaticParams() {
-
System.out.println("初始化构造方法");
-
}
-
-
public static StaticParams getInstance() {
-
return new StaticParams();
-
}
-
-
private static int getA() {
-
System.out.println("初始化A");
-
return 10;
-
}
-
-
private static int getB() {
-
System.out.println("初始化B");
-
return 20;
-
}
-
-
private static List<String> getListA() {
-
System.out.println("初始化List");
-
return new ArrayList<String>();
-
}
-
-
public static void main(String[] args) {
-
StaticParams.getInstance();
-
}
-
}
运行该程序,输出结果如下:
调整静态变量NUM_A和NUM_B的声明顺序,其他逻辑不变
然后再次运行该程序,输出结果如下:
说到这,想必聪明的程序员就想到问题原因了。即在某个静态变量的初始化还未执行之前就使用该静态变量。为了模拟该问题产生原因,我们修改上面的代码成一个单例模式,具体代码如下:
-
/**
-
*
-
*/
-
package com.mhy.oo.statics;
-
-
import java.util.ArrayList;
-
import java.util.List;
-
-
/**
-
* @author mhy2011@163.com
-
* @date 2011-11-18
-
*/
-
public class StaticParams {
-
-
private static StaticParams sp = buildStaticParams();
-
-
private static int NUM_A = getA();
-
private static int NUM_B = getB();
-
private static List<String> LIST_A = getListA();
-
-
/**
-
* 私有化构造方法
-
*/
-
private StaticParams() {
-
System.out.println("初始化构造方法");
-
}
-
-
/**
-
* sp的声明在其他几个静态变量之前
-
*
-
* @return
-
*/
-
private static StaticParams buildStaticParams() {
-
if (null == sp) {
-
sp = new StaticParams();
-
}
-
int result = NUM_A * NUM_B; // 基本类型有默认值,此处不会报错,但结果不正确
-
System.out.println("result is :" + result);
-
LIST_A.add("abcd"); //此时LIST_A还未初始化,到此有异常
-
return sp;
-
}
-
-
/**
-
* 获取StaticParams实例
-
*
-
* @return
-
*/
-
public static StaticParams getInstance() {
-
return sp;
-
}
-
-
private static int getA() {
-
System.out.println("初始化A");
-
return 10;
-
}
-
-
private static int getB() {
-
System.out.println("初始化B");
-
return 20;
-
}
-
-
private static List<String> getListA() {
-
System.out.println("初始化List");
-
return new ArrayList<String>();
-
}
-
-
public static void main(String[] args) {
-
StaticParams.getInstance();
-
}
-
}
-
在上面的例子中,sp变量初始化中使用到的其他的变量,但其他的静态变量还未初始化,故而在sp初始化时就会产生上面的异常,运行上面的程序就可以在控制台看到如下异常信息:
说到这里,想必大家在编程过程中就知道如何来避免该异常信息的产生了吧。
java.lang.ExceptionInInitializerError异常分析的更多相关文章
- java.lang.ExceptionInInitializerError异常
今天在开发的过程中,遇到java.lang.ExceptionInInitializerError异常,百度查了一下,顺便学习学习,做个笔记 静态初始化程序中发生意外异常的信号,抛出Exception ...
- java.lang.UnsupportedOperationException 异常分析
今天将一个数组转换成 List 然后进行 remove 操作时却抛出 java.lang.UnsupportedOperationException 异常. String pattern = &quo ...
- java.lang.ArrayIndexOutOfBoundsException异常分析及解决
这是一个非常常见的异常,从名字上看是数组下标越界错误,解决方法就是查看为什么下标越界. 下面是一个错误示例: Exception in thread "main" java.lan ...
- java.lang.ArrayIndexOutOfBoundsException 异常分析及解决
参考:http://blog.csdn.net/javaeeteacher/article/details/4485834 这是一个非常常见的异常,从名字上看是数组下标越界错误,解决方法就是查看为什么 ...
- “java.lang.NullPointerException”异常分析
1.父类定义的某个属性,没有被子类使用,或者在子类中,又重新定义一次. 2.因为调用了一个object的方法,且此object的reference为null:比如说:String a=null; // ...
- 记一次java.lang.NoClassDefFoundError异常
前阵子做了个评论过滤敏感词的功能,本地测试没有任何问题,然后就部署到线上服务器,通知相关人员线上测试.大约过了十来天,那货和我说接口出问题了,当时一脸懵逼,用了十来天突然出问题了???好吧,出问题了咱 ...
- java.lang.ExceptionInInitializerError
java.lang.ExceptionInInitializerError at com.csdhsm.compiler.test.DevTest.testReadInput(DevTest.java ...
- android java.lang.ExceptionInInitializerError
11-08 13:36:05.108: E/AndroidRuntime(5318): java.lang.ExceptionInInitializerError 11-08 13:36:05.108 ...
- springboot下jar包方式运行Caused by: java.lang.ExceptionInInitializerError: null
idea调试过程中不会出现此问题,异常如下 org.springframework.beans.factory.BeanCreationException: Error creating bean w ...
随机推荐
- 把java程序打包成.exe
准备工作:将可执行的jar包跟资源跟第三方包都放到一个目录下. 能够将jre包也放入里面.这样在没有安装jre的情况下也能够执行. watermark/2/text/aHR0cDovL2Jsb2cuY ...
- TabControl控件重绘
原文地址:http://www.codeproject.com/Articles/91387/Painting-Your-Own-Tabs-Second-Edition 在网上看到重绘TabContr ...
- 详解Spring Boot配置文件之多环境配置
一. 多环境配置的好处: 1.不同环境配置可以配置不同的参数~ 2.便于部署,提高效率,减少出错~ 二. properties多环境配置 1. 配置激活选项 spring.profiles.activ ...
- [Angular] New async 'as' syntax and ngIf.. else
From Anuglar v4 above, we are able to using 'as' with async pipe. This allow as using 'new variable' ...
- Ajax之旅(二)--XMLHttpRequest
上文中提到的Ajax的异步更新.主要使用XMLHttpRequest对象来实现的,XMLHttpRequest对象能够在不向server提交整个页面的情况下,实现局部更新网页. 当页面所有载 ...
- js进阶ajax函数封装(匿名函数作为参数传递)(封装函数引入文件的方式非常好用)
js进阶ajax函数封装(匿名函数作为参数传递)(封装函数引入文件的方式非常好用) 一.总结 2.匿名函数作为参数传递 二.js进阶ajax函数封装 ajax1.js function ajax(ur ...
- DC综合:划分与编码风格
划分与编码风格 合理的设计划分和好的HDL编码风格对成功的综合影响很大. 逻辑划分是成功综合(和布局布线,如果布图是层次化的)的关键. 综合划分 "分而治之" 把复杂的设计化简为更 ...
- LIGO找到首个超越广义相对论的证据?
转自 麻省理工科技评论 原文 LIGO找到首个超越广义相对论的证据? 1915年,爱因斯坦根据简单的原理提出广义相对论,极大地改变了人们的时空观.广义相对论不仅解释了牛顿理论无法解释的现象,还做出许多 ...
- 终端复用工具tmux的使用
tmux的作用在于终端复用. 1. 在server上启动一个bash.并在里面执行tmux 2. 通过ssh远程登录server,执行tmux attach,就会切换到server上的那个bash中, ...
- iOS开发Quartz2D 十三:画板涂鸦
一:效果如图: 二:代码 #import "ViewController.h" #import "DrawView.h" #import "Handl ...