java.lang.ExceptionInInitializerError

一.错误,原因


java.lang.ExceptionInInitializerError


二.原因

引起java.lang.ExceptionInInitializerError 错误的原因是:在类的初始化时,出错。也就是说,在加载类时,执行static的属性、方法块时,出错了。

比如

 

  1. <span style="font-family:Times New Roman;">public class AA{
  2. private static AA aa = new AA();
  3. private AA(){//构造方法
  4. init();
  5. }
  6. public void init(){
  7. .... }
  8. }</span>

初始化类时,会调用init方法,如果init方法出错,这类初始化失败,就会报java.lang.ExceptionInInitializerError错误。

同理,在执行

  1. static{
  2.   ...
  3. }


方法块时,也可能报这个错。


三.原因分析


      当在静态初始化块中出现了异常的时候,JVM会抛出 java.lang.ExceptionInInitializerError异常。

java中的静态变量,是在类加载的时候进行初始化的。如果在这个静态变量初始化的过程中出现了异常,就会抛出 java.lang.ExceptionInInitializerError异常。


      任何异常都可能会引发这种情况,比如说,java.lang.ArrayIndexOutOfBound或者java.lang.NullPointerException。我们通常会被这个错误弄晕,觉得自己并没有定义任何的静态初始化块,为什么还会抛出ExceptionInInitializerError异常;事实上,Java默认会将静态变量的初始化放在一个默认的静态初始化块中,然后按它们在源文件中声明的顺序来进行初始化。比如说变量ABC声明在第一行,在第二行中使用到了,而在第三行的时候才初始化,那么第二行的代码会抛出一个NullPointerException异常,这个异常会被封装到一个ExceptionInInitializerError异常中,如果这段代码在主线程中执行了,你会看到控制台或者日志文件中出现这样的错误信息: "Exception in thread "main"java.lang.ExceptionInInitializerError"。


       在一个拥有大量日志文件的大型系统中,这样的错误很容易被忽略,而程序员会得到一个java.lang.NoClassDefFoundError异常。不幸的是只有其他代码使用到了这个类的时候才会出现这个错误,因为ExceptionInInitializerError导致了这个类无法加载。由于类加载失败了,因此JVM会抛出NoClassDefFoundError。我们会去检查类路径,PATH,以及java.library.path看是不是缺少了这个类,却又发现不了任何问题。如果在分析NoClassDefFoundError的原因,最好看下你的日志文件中有没有ExceptionInInitializerError,然后再考虑要不要检查classpath。


Exception in thread"main" java.lang.ExceptionInInitializerError的原因 :


       正如别的错误或者异常一样,当看见这行信息,你知道这是出现ExceptionInInitializerError异常了,这个异常是由于类加载过程中静态块初始化过程失败所导致的。由于它出现在负责启动程序的主线程中,因此你最好从主类中开始分析,这里说的主类是指你在命令行参数中指定的那个,或者说是你声明了public static void main(String args[])方法的那个类。如果你仔细地看一下完整的堆栈跟踪信息,会发现引发ExceptionInInitializerError的类。ExceptionInInitializerError是LinkageError的子类,这意味着这个异常会导致你的类无法加载到JVM的内存中。现在我们来看一下这个示例程序。

 

  1. <span style="font-family:Times New Roman;">importjava.util.ArrayList;
  2. importjava.util.List;
  3. /**
  4. * Java Program to understand and solveExceptionInitializerError, which comes
  5. * When static initializer blocks throwsunchecked exception during class loading
  6. * and initialization.
  7. *
  8. * @author Javin Paul
  9. */
  10. public classStaticInitializerDemo{
  11. private static final List<CreditCard>cards = new ArrayList<CreditCard>();
  12. private static CreditCard prefferdCard =cards.get(0); // 1st card is default
  13. public static boolean isVisa ="VISA".equalsIgnoreCase(prefferdCard.getNetwork());
  14. public static void main(String args[]) {
  15. makePayment(prefferdCard);
  16. }
  17. public static void makePayment(CreditCard cc){
  18. if (isVisa) {
  19. //offer 5% discount
  20. }
  21. // deduct payment
  22. }
  23. }
  24. class CreditCard{
  25. private long card_number; //16 digit cardnumber
  26. private int cvv; // 3 digit cvv number
  27. private int expiryMonth;
  28. private int expiryYear;
  29. private String bank;
  30. private String network;
  31. public CreditCard(long card_number, int cvv,int expiryMonth, int expiryYear, String bank, String network) {
  32. super();
  33. this.card_number = card_number;
  34. this.cvv = cvv;
  35. this.expiryMonth = expiryMonth;
  36. this.expiryYear = expiryYear;
  37. this.bank = bank;
  38. this.network = network;
  39. }
  40. /**
  41. * @return the card_number
  42. */
  43. public final long getCard_number() {
  44. return card_number;
  45. }
  46. /**
  47. * @return the cvv
  48. */
  49. public final int getCvv() {
  50. return cvv;
  51. }
  52. /**
  53. * @return the expiryMonth
  54. */
  55. public final int getExpiryMonth() {
  56. return expiryMonth;
  57. }
  58. /**
  59. * @return the expiryYear
  60. */
  61. public final int getExpiryYear() {
  62. return expiryYear;
  63. }
  64. /**
  65. * @return the bank
  66. */
  67. public final String getBank() {
  68. return bank;
  69. }
  70. /**
  71. * @return the network
  72. */
  73. public final String getNetwork() {
  74. return network;
  75. }
  76. }
  77. </span>


输出:

  1. <span style="font-family:Times New Roman;">Exception inthread "main" java.lang.ExceptionInInitializerError
  2. Caused by:java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
  3. at java.util.ArrayList.rangeCheck(UnknownSource)
  4. at java.util.ArrayList.get(Unknown Source)
  5. atStaticInitializerDemo.<clinit>(StaticInitializerDemo.java:15)</span>


看一下栈跟踪信息,知道真正的异常是java.lang.IndexOutOfBoundsException,它在StaticInitiazerDemo的第二行被抛出来了。这是由于调用了ArrayList的get()方法并传入了位置0,而这个ArrayList的大小也是0(Index: 0, Size: 0)。看到这条信息后你知道当我们想从列表中取出第一张CreditCard时,这个列表是空的。


四.解决办法


解决注意事项:

如何解决Exception inthread "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块来进行处理。


需要谨记的是这个异常的一个副作用是NoClassDefFoundError,而Java程序抛出这个异常的位置可能会离java.lang.ExceptionInInitializerError很远,这取决于客户端代码何时引用到这个类。因此,在查看类路径解决NoClassDefFoundError异常之前,最好先看看日志有没有出现ExceptionInInitializerError。


五.参考网址


1.   http://www.2cto.com/kf/201309/241190.html

2.   http://www.tuicool.com/articles/IVBVn2

原文地址:https://blog.csdn.net/li1500742101/article/details/46049973
posted @ 2019-07-01 16:03  星朝  阅读(24330)  评论(0编辑  收藏  举报