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

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

    XMLWordPrintable

Details

    • Bug
    • Resolution: Fixed
    • P4
    • 1.4.1
    • 1.3.0, 1.4.0
    • hotspot
    • hopper
    • generic, x86
    • 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

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

              Dates

                Created:
                Updated:
                Resolved:
                Imported:
                Indexed: