Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-5053137

REGRESSION: ExceptionInInitializerError in inner classes

    XMLWordPrintable

Details

    • Bug
    • Resolution: Duplicate
    • P3
    • None
    • 1.4.2
    • tools
    • x86
    • windows_2000

    Description



      Name: js151677 Date: 05/26/2004


      FULL PRODUCT VERSION :
      java version "1.4.0"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-b92)
      Java HotSpot(TM) Client VM (build 1.4.0-b92, mixed mode)

      java version "1.4.1"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1-b21)
      Java HotSpot(TM) Client VM (build 1.4.1-b21, mixed mode)

      java version "1.4.2_04"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_04-b05)
      Java HotSpot(TM) Client VM (build 1.4.2_04-b05, mixed mode)


      ADDITIONAL OS VERSION INFORMATION :
      Windows 2000, Windows NT 4.0,
      Under MacOS-X the bug is confirmed using JDK 1.4.1

      A DESCRIPTION OF THE PROBLEM :
      When compiling a class using inner classes with static member variables with the javac compiler of JDK 1.4.x, a program using that class will abort with an ExceptionInInitializerError, caused by a NullPointerException during initialization of the affected class.

      The inner classes must be so called singletons or enumerative classes, that means, they must contain at least one static member object of the inner class type.

      The occurence of that bug heavily depends on the way the static class members are accessed from outside.

      Note also, that writing certain things in a different manner sometimes help. In the example code, replace the "String.class" at line 14 with "String().getClass()" would let the program run successfully... That should not happen.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Look at the example code beneath.
        To reproduce the bug, three facts are important:

      1) First access to the affected class must be an access of a static member variable of an inner class from outside the affected class.

      2) At least three inner classes, each with static member object variables of the same class type as the inner class.

      3) The containg class (in the example "OuterClass") must have a static member object variable containing one of the static member variable objects of the inner classes. Note, that this must be none of the inner class, that is being accessed first from outside the.




      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      Stack trace of ExceptionInInitializerError:
      java.lang.ExceptionInInitializerError
      at OuterClass.<clinit>(OuterClass.java:62)
      at OuterClass$C.<init>(OuterClass.java:14)
      at OuterClass$C.<clinit>(OuterClass.java:5)
      at OuterClass$AccessedClass.<init>(OuterClass.java:54)
      at OuterClass$AccessedClass.<clinit>(OuterClass.java:47)
      at BugDemo.main(BugDemo.java:7)
      Caused by: java.lang.NullPointerException
      at OuterClass$B.<init>(OuterClass.java:37)
      at OuterClass$B.<clinit>(OuterClass.java:29)
      ... 6 more

      Stack trace of causing Exception:
      java.lang.NullPointerException
      at OuterClass$B.<init>(OuterClass.java:37)
      at OuterClass$B.<clinit>(OuterClass.java:29)
      at OuterClass.<clinit>(OuterClass.java:62)
      at OuterClass$C.<init>(OuterClass.java:14)
      at OuterClass$C.<clinit>(OuterClass.java:5)
      at OuterClass$AccessedClass.<init>(OuterClass.java:54)
      at OuterClass$AccessedClass.<clinit>(OuterClass.java:47)
      at BugDemo.main(BugDemo.java:7)


      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
        To reproduce the error you need two source files.

      The 1st source contains the startup code:

      public class BugDemo
      {
          public static void main(String[] args) throws Exception
          {
              try
              {
                  OuterClass.AccessedClass tf = OuterClass.AccessedClass.accessedMember;
              }
              catch (ExceptionInInitializerError err)
              {
                  System.out.println("Stack trace of ExceptionInInitializerError:");
                  err.printStackTrace(System.out);
                  System.out.println();
                  System.out.println("Stack trace of causing Exception:");
                  err.getException().printStackTrace(System.out);
              }
          }
      }


      -------------------------------------------------------------------------------------
      The 2nd class contains all the "useful" and necessary stuff to present the error:

      public class OuterClass
      {
          private static class C
          {
              public static C member_C = new C();

              private C()
              {
                  //
                  // This line is also necessary to cause the bug.
                  // Obtaining a Class-object is important here,
                  // the name of the class is irrelevant.
                  //
                  Class cl = String.class;
                  
                  //
                  // This will work !!! (Why it does not cause the error?)
                  //
                  // Class cl = new String().getClass();
              }
          }


          private static class B
          {
              //
              // "member_B" will be the value of a static member variable of OuterClass.
              //
              public static B member_B = new B();

              private B()
              {
                  //
                  // Access "C.member_C" during creation of "member_B"...
                  // This is executed when the class OuterClass is initialized.
                  //
                  C.member_C.toString();
              }
          }


          public static class AccessedClass
          {
              //
              // "accessedMember" is accessed by the main program.
              //
              public static AccessedClass accessedMember = new AccessedClass();

              private AccessedClass()
              {
                  //
                  // Access "C.member_C" during creation of "accessedMember"...
                  //
                  C.member_C.toString();
              }
          }


          //
          // During initialization of OuterClass, the object "B.member_B" is created.
          //
          private static B mb = B.member_B;
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Compile with JDK 1.3.
      But if your project relies on JDK 1.4.x features, your only chance is to change the way you create and access static class member variables. But as you can see by the given example, a workaround may get somewhat odd.

      Release Regression From : 1.3.0
      The above release value was the last known release where this
      bug was known to work. Since then there has been a regression.

      (Incident Review ID: 275026)
      ======================================================================

      Attachments

        Issue Links

          Activity

            People

              gafter Neal Gafter
              jssunw Jitender S (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:
                Imported:
                Indexed: