-
Bug
-
Resolution: Fixed
-
P4
-
1.3.0, 1.4.0
-
hopper
-
generic, x86
-
generic
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
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
- duplicates
-
JDK-4304869 Incomplete initialization visible in contradiction of JLS
-
- Closed
-