今天在项目开发时遇到一个问题,整个项目是使用Spring等框架搭建起来的在运行项目时不报任何的异常信息,就是找不到某个类信息,各方查找该类确实是存在的,最后通过断点跟踪时在异常栈内发现java.lang.ExceptionInInitializerError这个异常信息,但这个异常信息没有在控制台或者日志系统中抛出来,查明原因之后就对症下药最终解决了该问题。查找该问题也着实费了一翻功夫,正好趁此机会把该问题引发的原因及针对这类问题应该如何来避免记录一下。由于该项目中的代码比较复杂,这里举一个简单的例子来说明一下该异常产生的原因。

java.lang.ExceptionInInitializerError

该异常在Java中的继承关系如下:

下面是jdk对该异常的描述

public class ExceptionInInitializerError

extends LinkageError

静态初始化程序中发生意外异常的信号。抛出 ExceptionInInitializerError 表明在计算静态初始值或静态变量的初始值期间发生异常

从版本 1.4 开始,这个异常已经更新过,符合通用异常链机制。“保存的 throwable 对象”可能是在构造的时候提供的,并且可以通过 getException() 方法来访问,这类对象目前被认为是导致异常的原因,可以通过 Throwable.getCause() 方法以及前面提到的“遗留方法”访问它。

要理解这个异常还得从Java类中的静态变量初始化过程说起,在Java类中静态变量的初始化顺序和静态变量的声明顺序是一致的。为了验证该说法,我们写一个简单的小程序,代码如下:


  1. /**
  2. *
  3. */
  4. package com.mhy.oo.statics;
  5. import java.util.ArrayList;
  6. import java.util.List;
  7. /**
  8. * @author mhy2011@163.com
  9. * @date 2011-11-18
  10. */
  11. public class StaticParams {
  12. private static int NUM_A = getA();
  13. private static int NUM_B = getB();
  14. private static List<String> LIST_A = getListA();
  15. private StaticParams() {
  16. System.out.println("初始化构造方法");
  17. }
  18. public static StaticParams getInstance() {
  19. return new StaticParams();
  20. }
  21. private static int getA() {
  22. System.out.println("初始化A");
  23. return 10;
  24. }
  25. private static int getB() {
  26. System.out.println("初始化B");
  27. return 20;
  28. }
  29. private static List<String> getListA() {
  30. System.out.println("初始化List");
  31. return new ArrayList<String>();
  32. }
  33. public static void main(String[] args) {
  34. StaticParams.getInstance();
  35. }
  36. }

运行该程序,输出结果如下:

调整静态变量NUM_A和NUM_B的声明顺序,其他逻辑不变

然后再次运行该程序,输出结果如下:

说到这,想必聪明的程序员就想到问题原因了。即在某个静态变量的初始化还未执行之前就使用该静态变量。为了模拟该问题产生原因,我们修改上面的代码成一个单例模式,具体代码如下:


  1. /**
  2. *
  3. */
  4. package com.mhy.oo.statics;
  5. import java.util.ArrayList;
  6. import java.util.List;
  7. /**
  8. * @author mhy2011@163.com
  9. * @date 2011-11-18
  10. */
  11. public class StaticParams {
  12. private static StaticParams sp = buildStaticParams();
  13. private static int NUM_A = getA();
  14. private static int NUM_B = getB();
  15. private static List<String> LIST_A = getListA();
  16. /**
  17. * 私有化构造方法
  18. */
  19. private StaticParams() {
  20. System.out.println("初始化构造方法");
  21. }
  22. /**
  23. * sp的声明在其他几个静态变量之前
  24. *
  25. * @return
  26. */
  27. private static StaticParams buildStaticParams() {
  28. if (null == sp) {
  29. sp = new StaticParams();
  30. }
  31. int result = NUM_A * NUM_B; // 基本类型有默认值,此处不会报错,但结果不正确
  32. System.out.println("result is :" + result);
  33. LIST_A.add("abcd"); //此时LIST_A还未初始化,到此有异常
  34. return sp;
  35. }
  36. /**
  37. * 获取StaticParams实例
  38. *
  39. * @return
  40. */
  41. public static StaticParams getInstance() {
  42. return sp;
  43. }
  44. private static int getA() {
  45. System.out.println("初始化A");
  46. return 10;
  47. }
  48. private static int getB() {
  49. System.out.println("初始化B");
  50. return 20;
  51. }
  52. private static List<String> getListA() {
  53. System.out.println("初始化List");
  54. return new ArrayList<String>();
  55. }
  56. public static void main(String[] args) {
  57. StaticParams.getInstance();
  58. }
  59. }

在上面的例子中,sp变量初始化中使用到的其他的变量,但其他的静态变量还未初始化,故而在sp初始化时就会产生上面的异常,运行上面的程序就可以在控制台看到如下异常信息:

说到这里,想必大家在编程过程中就知道如何来避免该异常信息的产生了吧。

java.lang.ExceptionInInitializerError异常分析的更多相关文章

  1. java.lang.ExceptionInInitializerError异常

    今天在开发的过程中,遇到java.lang.ExceptionInInitializerError异常,百度查了一下,顺便学习学习,做个笔记 静态初始化程序中发生意外异常的信号,抛出Exception ...

  2. java.lang.UnsupportedOperationException 异常分析

    今天将一个数组转换成 List 然后进行 remove 操作时却抛出 java.lang.UnsupportedOperationException 异常. String pattern = &quo ...

  3. java.lang.ArrayIndexOutOfBoundsException异常分析及解决

    这是一个非常常见的异常,从名字上看是数组下标越界错误,解决方法就是查看为什么下标越界. 下面是一个错误示例: Exception in thread "main" java.lan ...

  4. java.lang.ArrayIndexOutOfBoundsException 异常分析及解决

    参考:http://blog.csdn.net/javaeeteacher/article/details/4485834 这是一个非常常见的异常,从名字上看是数组下标越界错误,解决方法就是查看为什么 ...

  5. “java.lang.NullPointerException”异常分析

    1.父类定义的某个属性,没有被子类使用,或者在子类中,又重新定义一次. 2.因为调用了一个object的方法,且此object的reference为null:比如说:String a=null; // ...

  6. 记一次java.lang.NoClassDefFoundError异常

    前阵子做了个评论过滤敏感词的功能,本地测试没有任何问题,然后就部署到线上服务器,通知相关人员线上测试.大约过了十来天,那货和我说接口出问题了,当时一脸懵逼,用了十来天突然出问题了???好吧,出问题了咱 ...

  7. java.lang.ExceptionInInitializerError

    java.lang.ExceptionInInitializerError at com.csdhsm.compiler.test.DevTest.testReadInput(DevTest.java ...

  8. android java.lang.ExceptionInInitializerError

    11-08 13:36:05.108: E/AndroidRuntime(5318): java.lang.ExceptionInInitializerError 11-08 13:36:05.108 ...

  9. springboot下jar包方式运行Caused by: java.lang.ExceptionInInitializerError: null

    idea调试过程中不会出现此问题,异常如下 org.springframework.beans.factory.BeanCreationException: Error creating bean w ...

随机推荐

  1. linux终端下一些“风骚”的按键操作及Linux终端命令

    linux终端下一些"风骚"的按键操作 <backspace>  删除 <ctrl-l>     清空屏幕, 相当于clear tab            ...

  2. 2、opencv2.4.13.6安装

    一. 卸载opencv3.3.0: Going to the "build" folder directory of opencv from terminal, and execu ...

  3. 【例题 6-5 UVA 12657 】Boxes in a Line

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 双向链表模拟题. 移动的时候,要注意它就在所需要的位置的情况.那种情况不移动. (如果已经在所需位置了,还用链表的插入方式强行移动的 ...

  4. CSS布局开篇

    原文: 简书原文:https://www.jianshu.com/p/2c78b927f8c4 开篇 这是我写CSS布局的第一篇文章,之所以将布局从中摘出来单独放一部分是因为我觉得光是布局这块内容就有 ...

  5. minizlib

    ZLIB开源库采用的是DEFLATE压缩算法,已经不支持加密功能,实际上功能还存在于代码中,采用MINIZIP可以支持对ZIP文件的加解密. ZLIB目前最新的是1.2.7,MINIZIP最新的版本是 ...

  6. NASM Syntax

    NASM has a simplified syntax designed to let the user code with minimum overhead. In its simplest fo ...

  7. Swift 中异常抛出和四种异常处理

    在Swift中你可以像其他语言一样抛出异常处理异常,今天我们就详细地说说Swift中的异常抛出和处理. 在一开始我们要定义错误或者说是异常,Swift中的一些简单异常可以使用枚举定义,注意这个枚举要继 ...

  8. js中json法创建对象(json里面的:相当于js里面的=)

    js中json法创建对象(json里面的:相当于js里面的=) 一.总结 json里面的:相当于js里面的= 4.json创建js对象解决命名冲突:多个人为同一个页面写js的话,命名冲突就有可能发生, ...

  9. 最小生成树(MST)求解旅行商问题

    从当前位置开始(也可以不指定起始位置),访问完所有未访问的端点后返回起始点的最短路径就是连接所有端点的生成树.最小生成树需保证: 每条边最多只能被选 1 次: 抹掉所有未被选择的边时,图形不能分为上下 ...

  10. gdb常用调试命令以及多线程堆栈的查看

    GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具.或许,各位比较喜欢那种图形界面方式的,像VC.BCB等IDE的调试,但如果你是在UNIX平台下做软件,你会发现GDB这个调试工具有比VC ...