ExceptionInInitializerError异常

本文深入探讨了Java中静态变量初始化的过程,特别是在类加载机制下的准备和初始化阶段。通过一个具体的项目案例,分析了ExceptionInInitializerError异常的产生原因,揭示了静态变量初始化顺序与资源加载之间的关系。
摘要由CSDN通过智能技术生成

因为这个异常时在静态变量初始化发生异常时抛出的,所以首先我们了解一下静态变量初始化的问题

静态变量初始化

提到静态变量初始化,又不得不提JVM的类加载机制,把描述类的数据从class文件加载到内存,并对数据进行校验,转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制。

类加载的生命周期包括:加载,验证,准备,解析,初始化,使用和卸载这7个阶段。静态变量的初始化相关操作主要在准备和初始化阶段。

 

准备阶段

对于我们的静态变量来说,首先在准备阶段进行类变量内存的分配以及设置类变量初始值,(类变量是指被static修饰的变量),例如:

  public static int value = 123.
  //这时初始值为value = 0;

 

初始化阶段

初始化阶段是执行类构造器clinit()方法的过程:

  • clinit方法是有编译器自动收集类中所有类变量(类变量就是静态变量)的赋值动作和静态语句块(static{})块中的语句合并产生的,编译器收集顺序是 由语句在源文件中出现的顺序所决定的,静态语句块只能访问到定义在静态语句块之前的变量。

  • clinit()方法不需要显式调用父类构造器,虚拟机会保证在子类clinit()方法执行之前,父类的clinit()方法已经执行完毕。所以虚拟机第一个执行的肯定是java.lang.object.

  • 由于父类的clinit()方法先执行,也就意味着父类中定义的静态语句块要优于子类的变量赋值操作。

  • 如果一个类中没有静态语句块和堆变量赋值语句,编译器可以不为这个类生成clinit()方法。

所以由以上可以看出类变量的初始化顺序由它们在源文件中出现的顺序决定的,如果第一行声明了一个静态变量,它在第二行被使用,实际上它却在第三行被初始化,这样的情况就会出现变量初始化异常,具体异常就是NullPointerException异常

 

引起ExceptionInInitializerError异常的真凶

分析完了静态变量初始化问题,再来看具体引起ExceptionInInitializerError异常产生的原因是什么。在没碰到ExceptionInInitializerError异常的时候,我也不知道具体能引起它的原因有什么,所以我还是利用了搜索引擎Google了一下,发现任何异常都有可能引起ExceptionInInitializerError异常的发生,比如说:java.lang.ArrayIndexOutOfBound或者java.lang.NullPointerException。

 

再来具体看看我项目中的实际情况是什么:

我运行代码发现,控制台打印出了空指针的错误

  
  Exception in thread "main" java.lang.ExceptionInInitializerError
      at io.rong.util.CommonUtil.getCheckInfo(CommonUtil.java:340)
      at io.rong.util.CommonUtil.checkFiled(CommonUtil.java:73)
      at io.rong.methods.user.User.register(User.java:59)
      at io.rong.example.user.UserExample.main(UserExample.java:40)
  Caused by: java.lang.NullPointerException //空指针
      at io.rong.util.JsonUtil.<clinit>(JsonUtil.java:17)
      ... 4 more

 

空指针的错误具体位置是在:

  
  public class JsonUtil {
      private static final String JSONFILE = JsonUtil.class.getClassLoader().getResource("jsonsource").getPath()+"/";//这个地方报错
      ...
  }

即也就是在静态变量初始化的时候抛出的空指针异常。那么为什么会抛出空指针呢。接下来就要说JsonUtil.class.getClassLoader().getResource("jsonsource")的问题

class.getClassLoader()解析问题

getClassLoader()获取的是这个 类对象的加载器,只有Class类才有getClassLoader()方法,当一个类被虚拟机加载完毕过后,也就是上面所说的类加载机制,然后会创建一个Class类实例,用于虚拟机对类的管理,所以JsonUtil.class就是获得它的Class类,。

而JsonUtil.class.getClassLoader().getResource("jsonsource")就是在JsonUtil当前位置查找“jsonsource"这个资源文件。这是一个相对路径,实际上它返回的是一个URL.

  
   public URL getResource(String name) {
          URL url;
          ...

然后getPath(),就是获取这个URL的路径地址。但是却报出 java.lang.NullPointerException空指针异常。说明资源没找到。想想第三方平台肯定提供的资源的,结果仔细一看,是我没有把它SDK中的resources资源文件导入,所以找不到“jsonsource"资源,所以才报出空指针错误,从而报出ExceptionInInitializerError异常。这才找到了最终的真凶。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值