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

Can access statics in a partially <clinit>'d class

    Details

    • Type: Bug
    • Status: Closed
    • Priority: P4
    • Resolution: Fixed
    • Affects Version/s: 1.3.0, 1.4.0
    • Fix Version/s: 1.4.1
    • Component/s: hotspot
    • Labels:
    • Subcomponent:
    • Resolved In Build:
      hopper
    • CPU:
      generic, x86
    • OS:
      generic

      Description

      Running the following program shows the Y class/thread accessing statics in the X class/thread while X's <clinit> is still underway.

      Fails in HotSpot 1.3.1 & 1.4. Fails in CVM.
      Works in exact VM (classic as well?) and IBM's 1.3.0 JIT.
      Cliff Click


      class X extends Thread {
        public static final boolean _P; // TRUE after clinit

        // Class initializer
        static {
          // _P is FALSE here

          Y.fiddle_with_X(true);

          // Stall for a long time to allow adversary thread to get in
          try { sleep(2500); } catch (InterruptedException ix) {}

          _P = true; // set to TRUE here
        }

      }

      class Y extends Thread {
        public static void boolean b ) {

          if( b ) {
            System.out.println("Called from INSIDE X::<clinit>. Access to X's statics is OK. Expect to see false: ");
            System.out.println(X._P);

          } else {
            System.out.println("Called from OUTSIDE X::<clinit>. Access to X's statics should hang");
            System.out.println("If this prints TRUE , then we hung until X finished initializing");
            System.out.println("If this prints FALSE, then we peeked at X's statics before <clinit> was done");
            System.out.println(X._P);
          }
        }

        // What happens when we kick off a new Y?
        public void run() {

          // Sleep until X's <clinit> is underway
          try { sleep(150); } catch (InterruptedException ix) {}

          fiddle_with_X(false);
        }
      }


      public class clinit {

        public static void main( String args[] ) {

          // Make an adversarial Y thread.
          // It sleeps a little to let X::<clinit> get underway
          Y y = new Y();
          y.start();

          // Invoke X.<clinit> It will sleep for 2500.
          // Meanwhile Y should wake-up and access X's statics.
          boolean b = X._P;

          System.out.println("Called when all done. Access to X's statics is OK. Expect to see final value of true: ");
          System.out.println(b);

        }

      }


      ----

      A slightly harder test is to only access X._P once in fiddle_with_X,
      catching any VM that resolves the constant pool entry and quickens
      the getstatic the first time through:

        public static void fiddle_with_X( boolean b ) {

          boolean B = X._P;
          if( b ) {
      System.out.println("Called from INSIDE X::<clinit>. Access to X's statics is OK. Expect to see false: ");
      System.out.println(B);

          } else {
      System.out.println("Called from OUTSIDE X::<clinit>. Access to X's statics should hang");
      System.out.println("If this prints TRUE , then we hung until X finished initializing");
      System.out.println("If this prints FALSE, then we peeked at X's statics before <clinit> was done");
      System.out.println(B);
          }
        }

      This trips up every VM I've tried it with (1.1.8, 1.2, and the latest CVM.)

      ###@###.### 2001-08-20

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                coleenp Coleen Phillimore
                Reporter:
                cclicksunw Clifford Click (Inactive)
              • Votes:
                0 Vote for this issue
                Watchers:
                1 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved:
                  Imported:
                  Indexed: