Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 1024|回复: 1

[默认分类] java.lang.ExceptionInInitializerError异常分析

[复制链接]
  • TA的每日心情
    开心
    2021-12-13 21:45
  • 签到天数: 15 天

    [LV.4]偶尔看看III

    发表于 2020-8-17 14:22:15 | 显示全部楼层 |阅读模式

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

    下面是jdk对该异常的描述
      
      
       
       
      
    1. public class [b]ExceptionInInitializerError[/b]
    复制代码
    extends
    LinkageError
      
    静态初始化程序中发生意外异常的信号。抛出
    1. ExceptionInInitializerError
    复制代码
    表明在计算静态初始值或静态变量的初始值期间发生异常。  
    从版本 1.4 开始,这个异常已经更新过,符合通用异常链机制。“保存的 throwable 对象”可能是在构造的时候提供的,并且可以通过
    1. getException()
    复制代码
    方法来访问,这类对象目前被认为是导致异常的原因,可以通过
    1. Throwable.getCause()
    复制代码
    方法以及前面提到的“遗留方法”访问它。

    要理解这个异常还得从Java类中的静态变量初始化过程说起,在Java类中静态变量的初始化顺序和静态变量的声明顺序是一致的。为了验证该说法,我们写一个简单的小程序,代码如下:
      
    1. [code]
    2.    
    3.    
    4.      
    5.       
    6.       
    7.       
    8.       
    9.       
    10.        /**
    11.       
    12.       
    13.      
    14.       
    15.       
    16.       
    17.       
    18.       
    19.         *  
    20.       
    21.       
    22.      
    23.       
    24.       
    25.       
    26.       
    27.       
    28.         */
    29.       
    30.       
    31.      
    32.       
    33.       
    34.       
    35.       
    36.       
    37.        package com.mhy.oo.statics;
    38.       
    39.       
    40.      
    41.       
    42.       
    43.       
    44.       
    45.       
    46.       
    47.       
    48.      
    49.       
    50.       
    51.       
    52.       
    53.       
    54.        import java.util.ArrayList;
    55.       
    56.       
    57.      
    58.       
    59.       
    60.       
    61.       
    62.       
    63.        import java.util.List;
    64.       
    65.       
    66.      
    67.       
    68.       
    69.       
    70.       
    71.       
    72.       
    73.       
    74.      
    75.       
    76.       
    77.       
    78.       
    79.       
    80.        /**
    81.       
    82.       
    83.      
    84.       
    85.       
    86.       
    87.       
    88.       
    89.         * @author mhy2011@163.com
    90.       
    91.       
    92.      
    93.       
    94.       
    95.       
    96.       
    97.       
    98.         * @date 2011-11-18
    99.       
    100.       
    101.      
    102.       
    103.       
    104.       
    105.       
    106.       
    107.         */
    108.       
    109.       
    110.      
    111.       
    112.       
    113.       
    114.       
    115.       
    116.        public
    117.        class StaticParams {
    118.       
    119.       
    120.      
    121.       
    122.       
    123.       
    124.       
    125.       
    126.       
    127.       
    128.      
    129.       
    130.       
    131.       
    132.       
    133.       
    134.        private
    135.        static
    136.        int NUM_A = getA();
    137.       
    138.       
    139.      
    140.       
    141.       
    142.       
    143.       
    144.       
    145.        private
    146.        static
    147.        int NUM_B = getB();
    148.       
    149.       
    150.      
    151.       
    152.       
    153.       
    154.       
    155.       
    156.        private
    157.        static List<String> LIST_A = getListA();
    158.       
    159.       
    160.      
    161.       
    162.       
    163.       
    164.       
    165.       
    166.       
    167.       
    168.      
    169.       
    170.       
    171.       
    172.       
    173.       
    174.        private StaticParams() {
    175.       
    176.       
    177.      
    178.       
    179.       
    180.       
    181.       
    182.       
    183.         System.out.println(
    184.        "初始化构造方法");
    185.       
    186.       
    187.      
    188.       
    189.       
    190.       
    191.       
    192.       
    193.         }
    194.       
    195.       
    196.      
    197.       
    198.       
    199.       
    200.       
    201.       
    202.       
    203.       
    204.      
    205.       
    206.       
    207.       
    208.       
    209.       
    210.        public static StaticParams getInstance() {
    211.       
    212.       
    213.      
    214.       
    215.       
    216.       
    217.       
    218.       
    219.        return
    220.        new StaticParams();
    221.       
    222.       
    223.      
    224.       
    225.       
    226.       
    227.       
    228.       
    229.         }
    230.       
    231.       
    232.      
    233.       
    234.       
    235.       
    236.       
    237.       
    238.       
    239.       
    240.      
    241.       
    242.       
    243.       
    244.       
    245.       
    246.        private static int getA() {
    247.       
    248.       
    249.      
    250.       
    251.       
    252.       
    253.       
    254.       
    255.         System.out.println(
    256.        "初始化A");
    257.       
    258.       
    259.      
    260.       
    261.       
    262.       
    263.       
    264.       
    265.        return
    266.        10;
    267.       
    268.       
    269.      
    270.       
    271.       
    272.       
    273.       
    274.       
    275.         }
    276.       
    277.       
    278.      
    279.       
    280.       
    281.       
    282.       
    283.       
    284.       
    285.       
    286.      
    287.       
    288.       
    289.       
    290.       
    291.       
    292.        private static int getB() {
    293.       
    294.       
    295.      
    296.       
    297.       
    298.       
    299.       
    300.       
    301.         System.out.println(
    302.        "初始化B");
    303.       
    304.       
    305.      
    306.       
    307.       
    308.       
    309.       
    310.       
    311.        return
    312.        20;
    313.       
    314.       
    315.      
    316.       
    317.       
    318.       
    319.       
    320.       
    321.         }
    322.       
    323.       
    324.      
    325.       
    326.       
    327.       
    328.       
    329.       
    330.       
    331.       
    332.      
    333.       
    334.       
    335.       
    336.       
    337.       
    338.        private static List<String> getListA() {
    339.       
    340.       
    341.      
    342.       
    343.       
    344.       
    345.       
    346.       
    347.         System.out.println(
    348.        "初始化List");
    349.       
    350.       
    351.      
    352.       
    353.       
    354.       
    355.       
    356.       
    357.        return
    358.        new ArrayList<String>();
    359.       
    360.       
    361.      
    362.       
    363.       
    364.       
    365.       
    366.       
    367.         }
    368.       
    369.       
    370.      
    371.       
    372.       
    373.       
    374.       
    375.       
    376.       
    377.       
    378.      
    379.       
    380.       
    381.       
    382.       
    383.       
    384.        public static void main(String[] args) {
    385.       
    386.       
    387.      
    388.       
    389.       
    390.       
    391.       
    392.       
    393.         StaticParams.getInstance();
    394.       
    395.       
    396.      
    397.       
    398.       
    399.       
    400.       
    401.       
    402.         }
    403.       
    404.       
    405.      
    406.       
    407.       
    408.       
    409.       
    410.       
    411.         }
    412.       
    413.       
    414.    
    复制代码
      
      [/code]

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

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

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

    说到这,想必聪明的程序员就想到问题原因了。即在某个静态变量的初始化还未执行之前就使用该静态变量。为了模拟该问题产生原因,我们修改上面的代码成一个单例模式,具体代码如下:
      
    1. [code]
    2.    
    3.    
    4.      
    5.       
    6.       
    7.       
    8.       
    9.       
    10.        /**
    11.       
    12.       
    13.      
    14.       
    15.       
    16.       
    17.       
    18.       
    19.         *  
    20.       
    21.       
    22.      
    23.       
    24.       
    25.       
    26.       
    27.       
    28.         */
    29.       
    30.       
    31.      
    32.       
    33.       
    34.       
    35.       
    36.       
    37.        package com.mhy.oo.statics;
    38.       
    39.       
    40.      
    41.       
    42.       
    43.       
    44.       
    45.       
    46.       
    47.       
    48.      
    49.       
    50.       
    51.       
    52.       
    53.       
    54.        import java.util.ArrayList;
    55.       
    56.       
    57.      
    58.       
    59.       
    60.       
    61.       
    62.       
    63.        import java.util.List;
    64.       
    65.       
    66.      
    67.       
    68.       
    69.       
    70.       
    71.       
    72.       
    73.       
    74.      
    75.       
    76.       
    77.       
    78.       
    79.       
    80.        /**
    81.       
    82.       
    83.      
    84.       
    85.       
    86.       
    87.       
    88.       
    89.         * @author mhy2011@163.com
    90.       
    91.       
    92.      
    93.       
    94.       
    95.       
    96.       
    97.       
    98.         * @date 2011-11-18
    99.       
    100.       
    101.      
    102.       
    103.       
    104.       
    105.       
    106.       
    107.         */
    108.       
    109.       
    110.      
    111.       
    112.       
    113.       
    114.       
    115.       
    116.        public
    117.        class StaticParams {
    118.       
    119.       
    120.      
    121.       
    122.       
    123.       
    124.       
    125.       
    126.       
    127.       
    128.      
    129.       
    130.       
    131.       
    132.       
    133.       
    134.        private
    135.        static StaticParams sp = buildStaticParams();
    136.       
    137.       
    138.      
    139.       
    140.       
    141.       
    142.       
    143.       
    144.       
    145.       
    146.      
    147.       
    148.       
    149.       
    150.       
    151.       
    152.        private
    153.        static
    154.        int NUM_A = getA();
    155.       
    156.       
    157.      
    158.       
    159.       
    160.       
    161.       
    162.       
    163.        private
    164.        static
    165.        int NUM_B = getB();
    166.       
    167.       
    168.      
    169.       
    170.       
    171.       
    172.       
    173.       
    174.        private
    175.        static List<String> LIST_A = getListA();
    176.       
    177.       
    178.      
    179.       
    180.       
    181.       
    182.       
    183.       
    184.       
    185.       
    186.      
    187.       
    188.       
    189.       
    190.       
    191.       
    192.        /**
    193.       
    194.       
    195.      
    196.       
    197.       
    198.       
    199.       
    200.       
    201.         * 私有化构造方法
    202.       
    203.       
    204.      
    205.       
    206.       
    207.       
    208.       
    209.       
    210.         */
    211.       
    212.       
    213.      
    214.       
    215.       
    216.       
    217.       
    218.       
    219.        private StaticParams() {
    220.       
    221.       
    222.      
    223.       
    224.       
    225.       
    226.       
    227.       
    228.         System.out.println(
    229.        "初始化构造方法");
    230.       
    231.       
    232.      
    233.       
    234.       
    235.       
    236.       
    237.       
    238.         }
    239.       
    240.       
    241.      
    242.       
    243.       
    244.       
    245.       
    246.       
    247.       
    248.       
    249.      
    250.       
    251.       
    252.       
    253.       
    254.       
    255.        /**
    256.       
    257.       
    258.      
    259.       
    260.       
    261.       
    262.       
    263.       
    264.         * sp的声明在其他几个静态变量之前
    265.       
    266.       
    267.      
    268.       
    269.       
    270.       
    271.       
    272.       
    273.         *  
    274.       
    275.       
    276.      
    277.       
    278.       
    279.       
    280.       
    281.       
    282.         * @return
    283.       
    284.       
    285.      
    286.       
    287.       
    288.       
    289.       
    290.       
    291.         */
    292.       
    293.       
    294.      
    295.       
    296.       
    297.       
    298.       
    299.       
    300.        private static StaticParams buildStaticParams() {
    301.       
    302.       
    303.      
    304.       
    305.       
    306.       
    307.       
    308.       
    309.        if (
    310.        null == sp) {
    311.       
    312.       
    313.      
    314.       
    315.       
    316.       
    317.       
    318.       
    319.         sp =
    320.        new StaticParams();
    321.       
    322.       
    323.      
    324.       
    325.       
    326.       
    327.       
    328.       
    329.         }
    330.       
    331.       
    332.      
    333.       
    334.       
    335.       
    336.       
    337.       
    338.        int result = NUM_A * NUM_B;
    339.        // 基本类型有默认值,此处不会报错,但结果不正确
    340.       
    341.       
    342.      
    343.       
    344.       
    345.       
    346.       
    347.       
    348.         System.out.println(
    349.        "result is :" + result);
    350.       
    351.       
    352.      
    353.       
    354.       
    355.       
    356.       
    357.       
    358.         LIST_A.add(
    359.        "abcd");
    360.        //此时LIST_A还未初始化,到此有异常
    361.       
    362.       
    363.      
    364.       
    365.       
    366.       
    367.       
    368.       
    369.        return sp;
    370.       
    371.       
    372.      
    373.       
    374.       
    375.       
    376.       
    377.       
    378.         }
    379.       
    380.       
    381.      
    382.       
    383.       
    384.       
    385.       
    386.       
    387.       
    388.       
    389.      
    390.       
    391.       
    392.       
    393.       
    394.       
    395.        /**
    396.       
    397.       
    398.      
    399.       
    400.       
    401.       
    402.       
    403.       
    404.         * 获取StaticParams实例
    405.       
    406.       
    407.      
    408.       
    409.       
    410.       
    411.       
    412.       
    413.         *  
    414.       
    415.       
    416.      
    417.       
    418.       
    419.       
    420.       
    421.       
    422.         * @return
    423.       
    424.       
    425.      
    426.       
    427.       
    428.       
    429.       
    430.       
    431.         */
    432.       
    433.       
    434.      
    435.       
    436.       
    437.       
    438.       
    439.       
    440.        public static StaticParams getInstance() {
    441.       
    442.       
    443.      
    444.       
    445.       
    446.       
    447.       
    448.       
    449.        return sp;
    450.       
    451.       
    452.      
    453.       
    454.       
    455.       
    456.       
    457.       
    458.         }
    459.       
    460.       
    461.      
    462.       
    463.       
    464.       
    465.       
    466.       
    467.       
    468.       
    469.      
    470.       
    471.       
    472.       
    473.       
    474.       
    475.        private static int getA() {
    476.       
    477.       
    478.      
    479.       
    480.       
    481.       
    482.       
    483.       
    484.         System.out.println(
    485.        "初始化A");
    486.       
    487.       
    488.      
    489.       
    490.       
    491.       
    492.       
    493.       
    494.        return
    495.        10;
    496.       
    497.       
    498.      
    499.       
    500.       
    501.       
    502.       
    503.       
    504.         }
    505.       
    506.       
    507.      
    508.       
    509.       
    510.       
    511.       
    512.       
    513.       
    514.       
    515.      
    516.       
    517.       
    518.       
    519.       
    520.       
    521.        private static int getB() {
    522.       
    523.       
    524.      
    525.       
    526.       
    527.       
    528.       
    529.       
    530.         System.out.println(
    531.        "初始化B");
    532.       
    533.       
    534.      
    535.       
    536.       
    537.       
    538.       
    539.       
    540.        return
    541.        20;
    542.       
    543.       
    544.      
    545.       
    546.       
    547.       
    548.       
    549.       
    550.         }
    551.       
    552.       
    553.      
    554.       
    555.       
    556.       
    557.       
    558.       
    559.       
    560.       
    561.      
    562.       
    563.       
    564.       
    565.       
    566.       
    567.        private static List<String> getListA() {
    568.       
    569.       
    570.      
    571.       
    572.       
    573.       
    574.       
    575.       
    576.         System.out.println(
    577.        "初始化List");
    578.       
    579.       
    580.      
    581.       
    582.       
    583.       
    584.       
    585.       
    586.        return
    587.        new ArrayList<String>();
    588.       
    589.       
    590.      
    591.       
    592.       
    593.       
    594.       
    595.       
    596.         }
    597.       
    598.       
    599.      
    600.       
    601.       
    602.       
    603.       
    604.       
    605.       
    606.       
    607.      
    608.       
    609.       
    610.       
    611.       
    612.       
    613.        public static void main(String[] args) {
    614.       
    615.       
    616.      
    617.       
    618.       
    619.       
    620.       
    621.       
    622.         StaticParams.getInstance();
    623.       
    624.       
    625.      
    626.       
    627.       
    628.       
    629.       
    630.       
    631.         }
    632.       
    633.       
    634.      
    635.       
    636.       
    637.       
    638.       
    639.       
    640.         }
    641.       
    642.       
    643.      
    644.       
    645.       
    646.       
    647.       
    648.       
    649.       
    650.       
    651.    
    复制代码
      
      [/code]

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

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



    回复

    使用道具 举报

  • TA的每日心情
    难过
    2021-5-9 09:37
  • 签到天数: 14 天

    [LV.3]偶尔看看II

    发表于 2021-4-29 10:22:56 | 显示全部楼层
    大佬太厉害了
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-4-17 07:53 , Processed in 0.411404 second(s), 46 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表