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 ...
随机推荐
- [D3] Drawing path in D3
Here we have a force layout with three nodes. In the example, we will link three nodes with line and ...
- amazeui学习笔记--css(常用组件7)--输入框组Input-group
amazeui学习笔记--css(常用组件7)--输入框组Input-group 一.总结 1.使用:Input group 基于 Form 组件和 Button 组件扩展,依赖这两个组件.在容器上添 ...
- ssh远程执行命令并自动退出
usage: ssh [-1246AaCfgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec] [-D [bind_address:]port] [ ...
- Linux定时器的使用(三种方法)
使用定时器的目的无非是为了周期性的执行某一任务,或者是到了一个指定时间去执行某一个任务.要达到这一目的,一般有两个常见的比较有效的方法.一个是用linux内部的三个定时器,另一个是用sleep, us ...
- 在 Swift 项目中实现侧滑菜单-利用 SWRevealViewController
你可以完全自己手动写一个侧滑菜单,但是现在在 GitHub 上面已经有很多免费的开源库了,如果不是有很特别的需求,大可不必新建一个轮子. 在这里我使用的这个第三方库名字叫做 SWRevealViewC ...
- amazeui学习笔记--js插件(UI增强2)--按钮交互Button
amazeui学习笔记--js插件(UI增强2)--按钮交互Button 一.总结 1.按钮loading状态: <button type="button" class=&q ...
- Hadoop笔记(一)
1.大数据的概述 大数据:巨量数据.海量数据,首先在数据的量上达到一定的规模,首先是人或者计算机在不合理时间内是不能够实现的数据量. 2.特点:数据量比较大,数据类型多样化.处理速度问题 3.大数据平 ...
- CQRS之旅——旅程6(我们系统的版本管理)
旅程6:我们系统的版本管理 准备下一站:升级和迁移 "变化是生活的调味品."威廉·考珀 此阶段的最高目标是了解如何升级包含实现CQRS模式和事件源的限界上下文的系统.团队在这一阶段 ...
- UVA 10603 - Fill BFS~
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&c ...
- 2、qq物联环境搭建
1.使用easyopenjtag.openjtag来烧写uboot 2.体验uboot 插讲<网络设置_ping问题解决_远程登录ssh_文件互传ftp> 192.168.1.183 wi ...