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

rejecting class with two identical superinterfaces

    XMLWordPrintable

    Details

    • Subcomponent:
    • CPU:
      generic
    • OS:
      generic

      Description



      Name: vsR10008 Date: 07/27/2000



      JVM rejects a class which implements the same interface twice.
      Howevere we can't find in JVMS (Second Edition) that this is prohibited.
      We are not sure if this is a bug in implementation or an omission in the spec.
      Something should be fixed.

      Let's consider the following example:

      interface A {...}
      interface A1 extends A {}
      interface A2 extends A {}
      class B implements A1,A2 {...}
      class C implements A,A {...}

      Class B and C are semantically equal; so
      JVM should accept both B and C or reject them both.
      Meanwhile JVM accepts "B" but rejects "C".

      Note, that JLS explicitly prohibits such usage of interfaces
      (JLS, 2nd edition, "8.1.4 Superinterfaces"):

        A compile-time error occurs if the same interface is mentioned two or
        more times in a single "implements" clause.

      We cannot compile class C from the example above with usual Java compiler,
      so we use jcod utility to make appropriate classfile.

      The following sources demonstrate the bug:

      --------------------------------------------------------------- D.java ---
      interface A {
          void m() {}
      }
      interface A1 extends A {}
      interface A2 extends A {}
      class B implements A1,A2 {
          public void m() {}
      }
      // class C implements A,A {} -- see C.jcod

      public class D {
          public void m() {}
          public static void main(String[] argv) {
              String[] cn={"B","C"};
              for(int i=0;i<cn.length;i++) {
                 try {
                    System.out.print("Loading class "+cn[i]+"...");
                    Class.forName(cn[i]);
                    System.out.println("Loaded!");
                 } catch (Throwable t) {
                    System.out.println("ERROR:"+t);
                 }
              }
          }
      }
      --------------------------------------------------------------- C.jcod ---
      class C {
        0xCAFEBABE;
        3; // minor version
        45; // version
        [] { // Constant Pool
          ; // first element is empty
          Method #3 #11; // #1
          class #12; // #2
          class #13; // #3
          class #14; // #4
          Utf8 "<init>"; // #5
          Utf8 "()V"; // #6
          Utf8 "Code"; // #7
          Utf8 "LineNumberTable"; // #8
          Utf8 "SourceFile"; // #9
          Utf8 "D.java"; // #10
          NameAndType #5 #6; // #11
          Utf8 "C"; // #12
          Utf8 "java/lang/Object"; // #13
          Utf8 "A"; // #14
        } // Constant Pool

        0x0020; // access
        #2;// this_cpx
        #3;// super_cpx

        [] { // Interfaces
        // ... implements A,A
          #4;
          #4;
        } // Interfaces

        [] { // fields
        } // fields

        [] { // methods
          { // Member
            0x0000; // access
            #5; // name_cpx
            #6; // sig_cpx
            [] { // Attributes
              Attr(#7) { // Code
                1; // max_stack
                1; // max_locals
                Bytes[] {
                  0x2AB70001B1;
                };
                [] { // Traps
                } // end Traps
                [] { // Attributes
                  Attr(#8) { // LineNumberTable
                    [] { // LineNumberTable
                      0 5;
                    }
                  } // end LineNumberTable
                } // Attributes
              } // end Code
            } // Attributes
          } // Member
        } // methods

        [] { // Attributes
          Attr(#9) { // SourceFile
            #10;
          } // end SourceFile
        } // Attributes
      } // end class C
      --------------------------------------------------------------------------

      Execution log:

      > uname -a

      SunOS novo12 5.7 Generic_Patch sun4u sparc SUNW,Ultra-2

      > java -version

      java version "1.4.0beta"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0beta-b25)
      Java HotSpot(TM) Core VM (build 1.3-internal, interpreted mode)

      > java -classic -version

      java version "1.4.0beta"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0beta-b25)
      Classic VM (build 1.4.0beta-b25, green threads, nojit)

      > jcod C.jcod

      > javac D.java

      > java D

      Loading class B...Loaded!
      Loading class C...ERROR:java.lang.ClassFormatError: C (Repeative interface name)

      > java -classic D

      Loading class B...Loaded!
      Loading class C...ERROR:java.lang.ClassFormatError: C (Repeative interface name)

      This bug doesn't occur in JDK1.0, JDK1.0.1, JDK1.0.2

      In JDK 1.1-1.1.2 JVM rejects class "C" throwing
      "java.lang.IllegalAccessError: Unimplemented interface method".

      In JDK 1.1.3-1.1.5 JVM rejects class "C" throwing
      "java.lang.VerifyError: Bad interface index"

      In JDK 1.1.6-1.1.8 JVM rejects class "C" throwing
      java.lang.ClassFormatError: Bad interface index

      In JDK 1.2-1.4 JVMs (both classic and HotSpot) reject class "C" throwing
      java.lang.ClassFormatError: C (Repeative interface name)

      ======================================================================

      In the above example, class B is legal and class C is not. The VM is doing the right thing.

      ###@###.### 2002-04-11

        Attachments

          Activity

            People

            Assignee:
            wtaosunw Wei Tao (Inactive)
            Reporter:
            atwosunw A2 A2 (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Dates

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: