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

Virtual Machine initializes too many classes

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: P4 P4
    • None
    • 1.3.0
    • hotspot
    • generic
    • generic



      Name: boT120536 Date: 03/09/2001


      java version "1.3.0_01"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0_01)
      Java HotSpot(TM) Client VM (build 1.3.0_01, mixed mode)


      The virtual machine initializes a class in violation of JLS2 12.4.1 and JVMS2
      5.4.3, 5.5, and 6. Referencing a class via invokestatic, getstatic, or
      putstatic, should only initialize the class if that class also declares the
      static member being referenced.

      First, compile these three source files:

      class A {
        static void foo() {
          System.out.println("A");
        }
        static {
          System.out.println("Init. A");
        }
      }

      class B extends A {
        static void foo() {
          System.out.println("B");
        }
        static {
          System.out.println("Init. B");
        }
      }

      class Test {
        public static void main(String[] args) {
          B.foo();
        }
      }

      Note that Test.class now includes the bytecode invokestatic B.foo(). Now,
      comment out the declaration of foo inside B, and recompile just B.java, so that
      the call in Test.main to B.foo() will end up invoking the inherited A.foo():

      class B extends A {
        static {
          System.out.println("Init. B");
        }
      }

      Now, when executing these files, the output is:

      $ ls -l *.class
      -rw-r--r-- 1 eblake fpga 442 Mar 9 14:50 A.class
      -rw-r--r-- 1 eblake fpga 367 Mar 9 15:13 B.class
      -rw-r--r-- 1 eblake fpga 482 Mar 9 15:11 Hello.class
      $ java Hello
      Init. A
      Init. B
      A

      This means that the virtual machine, when resolving the invokestatic B.foo()
      call, initialized class B (which of course initializes the superclass A first).

      However, quoting JVMS 6 on invokestatic bytecode:
      "On successful resolution of the method, the class that declared the resolved
      field is initialized (?5.5) if that class has not already been initialized."
      Likewise, in JLS 12.4.1, a class T is initialized if "T is a class and a static
      method declared by T is invoked," and B does not declare foo(). Therefore, B
      should not be initialized, and the correct output should be:

      Init. A
      A

      (Note that a clean compilation of all three files, using the second version of
      B, will give the correct output, but that this is due to a bug in javac.
      According to JLS 15.12.1, 13.1, and 13.4.11, the bytecode emitted in Test.class
      should refer to B.foo() whether B declares or inherits foo, but javac currently
      emits a reference to A.foo() when B does not declare foo.)
      (Review ID: 118533)
      ======================================================================

            Unassigned Unassigned
            bonealsunw Bret O'neal (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: