Java中的ExceptionInInitializerError异常及解决方法
2019独角兽企业重金招聘Python工程师标准>>>
当在静态初始化块中出现了异常的时候,JVM会抛出 java.lang.ExceptionInInitializerError异常。如果你了解Java中的静态变量,你会知道它们是在类加载的时候进行初始化的。如果在这个静态变量初始化的过程中出现了异常,那么就会抛出 java.lang.ExceptionInInitializerError异常。任何异常都可能会引发这种情况,比如说,java.lang.ArrayIndexOutOfBound或者java.lang.NullPointerException。Java开发人员通常会被这个错误弄晕,他觉得自己并没有定义任何的静态初始化块,为什么还会抛出ExceptionInInitializerError异常;事实上,Java默认会将静态变量的初始化放在一个默认的静态初始化块中,然后按它们在源文件中声明的顺序来进行初始化。比如说变量ABC声明在第一行,在第二行中使用到了,而在第三行的时候才初始化,那么第二行的代码会抛出一个NullPointerException异常,这个异常会被封装到一个ExceptionInInitializerError异常中,如果这段代码在主线程中执行了,你会看到控制台或者日志文件中出现这样的错误信息: "Exception in thread "main" java.lang.ExceptionInInitializerError"。在一个拥有大量日志文件的大型系统中,这样的错误很容易被忽略,而程序员会得到一个java.lang.NoClassDefFoundError异常。不幸的是只有当别人使用到了这个类的时候才会出现这个错误,因为ExceptionInInitializerError导致了这个类无法加载。由于类加载失败了,因此JVM会抛出NoClassDefFoundError。有的时候这会误导Java开发人员,他们会检查类路径,PATH,以及java.library.path看是不是缺少了这个类,却又发现不了任何问题,这让他们很困惑。如果你在分析NoClassDefFoundError的原因,你最好看下你的日志文件中有没有ExceptionInInitializerError,然后再考虑要不要检查classpath。本文中我们将看到一段代码,它会在静态初始化过程中引发异常从而导致 "Exception in thread "main" java.lang.ExceptionInInitializerError"。在稍后的部分,我们将会看到如何去解决这个问题。
Exception in thread "main" java.lang.ExceptionInInitializerError的原因
正如别的错误或者异常一样,当你看见这行信息,你知道这是出现ExceptionInInitializerError异常了,这个异常是由于类加载过程中静态块初始化过程失败所导致的。由于它出现在负责启动程序的主线程中,因此你最好从主类中开始分析,这里说的主类是指你在命令行参数中指定的那个,或者说是你声明了public static void main(String args[])方法的那个类。如果你仔细地看一下完整的堆栈跟踪信息,你其实什么也不用做,因为JVM已经把类名给打印出来了,这就是引发ExceptionInInitializerError的类。ExceptionInInitializerError是LinkageError的子类,这意味着这个异常会导致你的类无法加载到JVM的内存中。现在我们来看一下这个示例程序,它在执行的时候会抛出下面的异常:
Java代码
Exception in thread "main" java.lang.ExceptionInInitializerError
Caused by: java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.rangeCheck(ArrayList.java:635)
at java.util.ArrayList.get(ArrayList.java:411)
at StaticInitiazerDemo.<clinit>(StaticInitiazerDemo.java:15)
Exception in thread "main" java.lang.ExceptionInInitializerError
Caused by: java.lang.IndexOutOfBoundsException: Index: 0, Size: 0at java.util.ArrayList.rangeCheck(ArrayList.java:635)at java.util.ArrayList.get(ArrayList.java:411)at StaticInitiazerDemo.<clinit>(StaticInitiazerDemo.java:15)
看一下栈跟踪信息,你知道真正的异常是java.lang.IndexOutOfBoundsException,它在StaticInitiazerDemo的第二行被抛出来了。这是由于你调用了ArrayList的get()方法并传入了位置0,而这个ArrayList的大小也是0(Index: 0, Size: 0)。看到这条信息后你知道当我们想从列表中取出第一张CreditCard时,这个列表是空的。
Java代码
import java.util.ArrayList;
import java.util.List;
/**
* Java Program to understand and solve ExceptionInitializerError, which comes
* When static initializer blocks throws unchecked exception during class loading
* and initialization.
*
* @author Javin Paul
*/
public class StaticInitializerDemo{
private static final List<CreditCard> cards = new ArrayList<CreditCard>();
private static CreditCard prefferdCard = cards.get(0); // 1st card is default
public static boolean isVisa = "VISA".equalsIgnoreCase(prefferdCard.getNetwork());
public static void main(String args[]) {
makePayment(prefferdCard);
}
public static void makePayment(CreditCard cc) {
if (isVisa) {
//offer 5% discount
}
// deduct payment
}
}
class CreditCard {
private long card_number; //16 digit card number
private int cvv; // 3 digit cvv number
private int expiryMonth;
private int expiryYear;
private String bank;
private String network;
public CreditCard(long card_number, int cvv, int expiryMonth, int expiryYear, String bank, String network) {
super();
this.card_number = card_number;
this.cvv = cvv;
this.expiryMonth = expiryMonth;
this.expiryYear = expiryYear;
this.bank = bank;
this.network = network;
}
/**
* @return the card_number
*/
public final long getCard_number() {
return card_number;
}
/**
* @return the cvv
*/
public final int getCvv() {
return cvv;
}
/**
* @return the expiryMonth
*/
public final int getExpiryMonth() {
return expiryMonth;
}
/**
* @return the expiryYear
*/
public final int getExpiryYear() {
return expiryYear;
}
/**
* @return the bank
*/
public final String getBank() {
return bank;
}
/**
* @return the network
*/
public final String getNetwork() {
return network;
}
}
import java.util.ArrayList;
import java.util.List;/*** Java Program to understand and solve ExceptionInitializerError, which comes* When static initializer blocks throws unchecked exception during class loading* and initialization.** @author Javin Paul*/public class StaticInitializerDemo{private static final List<CreditCard> cards = new ArrayList<CreditCard>();private static CreditCard prefferdCard = cards.get(0); // 1st card is defaultpublic static boolean isVisa = "VISA".equalsIgnoreCase(prefferdCard.getNetwork());public static void main(String args[]) {makePayment(prefferdCard);}public static void makePayment(CreditCard cc) {if (isVisa) {//offer 5% discount}// deduct payment}}class CreditCard {private long card_number; //16 digit card numberprivate int cvv; // 3 digit cvv numberprivate int expiryMonth;private int expiryYear;private String bank;private String network;public CreditCard(long card_number, int cvv, int expiryMonth, int expiryYear, String bank, String network) {super();this.card_number = card_number;this.cvv = cvv;this.expiryMonth = expiryMonth;this.expiryYear = expiryYear;this.bank = bank;this.network = network;}/*** @return the card_number*/public final long getCard_number() {return card_number;}/*** @return the cvv*/public final int getCvv() {return cvv;}/*** @return the expiryMonth*/public final int getExpiryMonth() {return expiryMonth;}/*** @return the expiryYear*/public final int getExpiryYear() {return expiryYear;}/*** @return the bank*/public final String getBank() {return bank;}/*** @return the network*/public final String getNetwork() {return network;}
}
输出:
Java代码
Exception in thread "main" java.lang.ExceptionInInitializerError
Caused by: java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.rangeCheck(Unknown Source)
at java.util.ArrayList.get(Unknown Source)
at StaticInitializerDemo.<clinit>(StaticInitializerDemo.java:15)
Exception in thread "main" java.lang.ExceptionInInitializerError
Caused by: java.lang.IndexOutOfBoundsException: Index: 0, Size: 0at java.util.ArrayList.rangeCheck(Unknown Source)at java.util.ArrayList.get(Unknown Source)at StaticInitializerDemo.<clinit>(StaticInitializerDemo.java:15)
这里是Java中所有Error类的类结构。你可以看到ExceptionInInitializerError是继承自LinkageError的。还应当知道的是,像RuntimeException一样,Error也是未检查异常,编译器是不去检查有没有相应的异常处理代码的。
如何解决Exception in thread "main" java.lang.ExceptionInInitializerError
需要记住以下几点:
1. "Exception in thread "main" java.lang.ExceptionInInitializerError"意味着异常出现在主线程,并且是LinkageError的一个子类java.lang.ExceptionInInitializerError,这是JVM类加载失败时才抛出的,原因是静态初始化代码中出现了诸如IndexOutOfBoundsException或者NullPointerException这样的RuntimeException。
2. 记住JVM会将所有的静态变量的初始化按它们在源文件中的出现顺序放到一个静态初始化块中。因此,不要觉得没有看到静态初始块就认为不会出现这个异常。事实上,你得确保静态变量的正确顺序,比如说,如果 一个变量初始化的时候用到了另一个变量,你得确保这个变量在前面已经初始化过了。
3. 如果别的代码想要使用这个类,则会抛出ExceptionInInitializerError异常,而它又会导致ClassNotFoundException或者NoClassDefFoundError。为什么?因为这个类加载失败了,并没有加载到JVM的内存中。因此如果你在解决类不存在之类的异常时,先看看你的日志文件中有没有这个异常。
4. 记住静态初始化代码块会抛出RuntimeException而不是已检查异常,而后者需要有对应的catch块来进行处理。
这就是关于Exception in thread "main" java.lang.ExceptionInInitializerError的所有东西了。你已经了解到了如何去跟踪此类问题,并找出抛出这个异常的罪魁祸首。需要谨记的是这个异常的一个副作用是NoClassDefFoundError,而Java程序抛出这个异常的位置可能会离java.lang.ExceptionInInitializerError很远,这取决于你的客户端代码何时引用到这个类。因此,在查看类路径解决NoClassDefFoundError异常之前,最好先看看日志有没有出现ExceptionInInitializerError。
转载于:https://my.oschina.net/solarxie/blog/650961
Java中的ExceptionInInitializerError异常及解决方法相关推荐
- android开发中遇到的异常及解决方法
每次运行项目,可能因为粗心或者哪一行代码没有调用,会导致项目不能运行,出现异常. 以下就是我总结的各种异常,会一直更新. 1. Unable to find explicit activity cla ...
- android应用开发中收集的异常日志解决方法记录
这里主要是列出开发中收集的一些错误日志,以及解决方案,仅供参考,也有待解决的问题 1, ListView 中出现java.lang.IndexOutOfBoundsException: Invalid ...
- 关于java中空指针异常的原因及解决方法
java中空指针异常,是一种很常见很普通的错误,初学的时候可能会感觉很难解决,代码写多了就好啦,下面总结一些java中空指针异常的一些内容. 首先,在开始之前,还是想说,对于一门编程语言,你要了解它的 ...
- DXF搭建过程中常见的异常及解决方法
台服dnf搭建过程中可能会出现一些大大小小的问题,这里就个人搭建经验单独做一下总结. 1.缺依赖: ./df_bridge_r: error while loading shared librarie ...
- java 插入 mysql 乱码_解决java中插入mysql中文乱码的方法
解决java中插入mysql中文乱码的方法 发布时间:2020-07-11 14:35:11 来源:亿速云 阅读:100 作者:清晨 这篇文章主要介绍解决java中插入mysql中文乱码的方法,文中介 ...
- java开发中遇到的问题及解决方法(持续更新)
java开发中遇到的问题及解决方法(持续更新) 参考文章: (1)java开发中遇到的问题及解决方法(持续更新) (2)https://www.cnblogs.com/LiuYanYGZ/p/6112 ...
- JQuery中使用Ajax赋值给全局变量失败异常的解决方法,jqueryajax
我们在用JQuery的Ajax从后台提取数据后想把它赋值给全局变量,但是却怎么都赋不进,为什么呢? 原因其实很简单,我们用的Ajax是异步操作,也就是说在你赋值的时候数据还没提取出来,你当然赋不进去, ...
- opencv 配置及测试中遇到的问题及解决方法(Microsoft C++ 异常: cv::Exception,位于内存位置 问题)
opencv 配置及测试中遇到的问题及解决方法 这是我第一次使用 opencv,配置是opencv3.4.1和Visual Studio 2019.本文主要写的是我在 配置 和 编写运行第一个测试程序 ...
- linux 图标显示 异常,在Ubuntu 18.04系统中VSCode图标显示异常的解决方法
以下介绍在Ubuntu 18.04系统中VSCode图标显示异常的解决方法,同时附上在Ubuntu 18.04系统中安装Anaconda3-5.3.0方法.VSCode是一款全平台开发的编辑器,它具有 ...
最新文章
- suse linux 命令
- css input[type=file] 样式美化,input上传按钮美化
- Configuration类在网页实现对web.config的修改[转]
- ubuntu下文件名乱码的解决办法
- ViewPager两种方式实现无限轮播
- 带给你灵感的3D街画艺术设计
- L-BFGS算法/Broyden族/BFGS算法/阻尼牛顿法的Python实现代码
- 更简洁的方式修改Chrome的User Agent,轻松体验移动版网络
- JSP, C 写入文件添加BOM头实例
- 自注意力机制_自注意力机制在计算机视觉中的应用【附PPT与视频资料】
- Yii2学习笔记002---Yii2的控制器和视图
- C++之---友元函数
- 怎么求平均数_小学奥数知识点趣味学习——平均数问题
- 分布式配置管理平台VS统一集中配置管理
- 实验十七 通信录csv文件管理
- Vue中数字(金额)大小写实时转换
- YOLO系列代码解读(图像检测)
- java有阴历年算法吗_中国农历算法java实现
- 一些小软件闪退的解决方案
- 单片机C语言DA转换,51单片机PCF8591的DA转换程序详解[含HL-1与HJ-c52 DA代码AD/DA原理图](可直接复......