今天在项目开发时遇到一个问题,整个项目是使用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. js里的表格数组某个key去重

    如Elemgnt的table绑定的数据要某个key是唯一的 var myarry = [ {name: 'liuyang',age :13}, {name:'jike',age:15}, {name: ...

  2. 读<阿里亿级日活网关通道架构演进>有感

    读<阿里亿级日活网关通道架构演进>时对优化方法有些概念不理解,特意搜索了一下,拓展自己的思路. 其中的优化: 优化方法中1,2比较常见,3,4我知道的比较少,很感兴趣.就继续追踪下去: 于 ...

  3. 全双工 串口 stm32

  4. BI并不是万能,中层业务管理报表要另辟蹊径

           BI是商业智能的缩写,是能够帮助企业做出明智的业务经营决策的工具.其数据来源于各个业务系统.如ERP.CRM.SCM.进销存.HER.OA等.        BI系统不同于传统的管理信息 ...

  5. 英特尔投资:7200万美元投资12家创新公司,包括3家中国公司(www.intelcapital.com)

    集微网消息,英特尔投资——英特尔公司全球投资机构,今天在英特尔投资全球峰会上宣布向12家科技创业公司投资超过7200万美元.加上今天宣布的新投资,英特尔投资在2018年投资总额已超过1.15亿美元. ...

  6. 24、驱动调试之printk

    1.uboot跳转到内核启动的时候通过环境变量 console设置控制台 (console = ttySAC0表示输出到串口,并从串口结束输入,也可以设置console=tty1,表示输出到LCD,从 ...

  7. 3D 应用程序性能

    原文:3D 应用程序性能 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/m0_37591671/article/details/74595999 3 ...

  8. [Angular2 Form] Reactive form: valueChanges, update data model only when form is valid

    For each formBuild, formControl, formGroup they all have 'valueChanges' prop, which is an Observable ...

  9. Setup iOS Development Environment.

    Setup iOS Development Environment Install XCode and check-out source code from SVN XCode Please find ...

  10. 使用Array和[]创建数组的区别

    原文 简书原文:https://www.jianshu.com/p/57a337d20aea 大纲 前言 对使用Array和[]创建数组的区别的解释 个人理解 前言 JS定义数组变量时,在不需要给定数 ...