< prev index next >

test/hotspot/jtreg/runtime/clinit/ClassInitBarrier.java

Print this page




  97         static void testInvokeStaticSync(Runnable action)    { A.staticS(action); }
  98         static void testInvokeStaticNative(Runnable action)  { A.staticN(action); }
  99 
 100         static int  testGetStatic(Runnable action)    { int v = A.staticF; action.run(); return v;   }
 101         static void testPutStatic(Runnable action)    { A.staticF = 1;     action.run(); }
 102         static A    testNewInstanceA(Runnable action) { A obj = new A();   action.run(); return obj; }
 103         static B    testNewInstanceB(Runnable action) { B obj = new B();   action.run(); return obj; }
 104 
 105         static int  testGetField(A recv, Runnable action)      { int v = recv.f; action.run(); return v; }
 106         static void testPutField(A recv, Runnable action)      { recv.f = 1;     action.run(); }
 107         static void testInvokeVirtual(A recv, Runnable action) { recv.m();       action.run(); }
 108 
 109         static void runTests() {
 110             checkBlockingAction(Test::testInvokeStatic);       // invokestatic
 111             checkBlockingAction(Test::testInvokeStaticNative); // invokestatic
 112             checkBlockingAction(Test::testInvokeStaticSync);   // invokestatic
 113             checkBlockingAction(Test::testGetStatic);          // getstatic
 114             checkBlockingAction(Test::testPutStatic);          // putstatic
 115             checkBlockingAction(Test::testNewInstanceA);       // new
 116 
 117             A recv = testNewInstanceB(NON_BLOCKING.get());  // trigger B initialization
 118             checkNonBlockingAction(Test::testNewInstanceB); // new: NO BLOCKING: same thread: A being initialized, B fully initialized
 119 
 120             checkNonBlockingAction(recv, Test::testGetField);      // getfield
 121             checkNonBlockingAction(recv, Test::testPutField);      // putfield
 122             checkNonBlockingAction(recv, Test::testInvokeVirtual); // invokevirtual
 123         }
 124 
 125         static void warmup() {
 126             for (int i = 0; i < 20_000; i++) {
 127                 testInvokeStatic(      NON_BLOCKING_WARMUP);
 128                 testInvokeStaticNative(NON_BLOCKING_WARMUP);
 129                 testInvokeStaticSync(  NON_BLOCKING_WARMUP);
 130                 testGetStatic(         NON_BLOCKING_WARMUP);
 131                 testPutStatic(         NON_BLOCKING_WARMUP);
 132                 testNewInstanceA(      NON_BLOCKING_WARMUP);
 133                 testNewInstanceB(      NON_BLOCKING_WARMUP);
 134 
 135                 testGetField(new B(),      NON_BLOCKING_WARMUP);
 136                 testPutField(new B(),      NON_BLOCKING_WARMUP);
 137                 testInvokeVirtual(new B(), NON_BLOCKING_WARMUP);
 138             }
 139         }
 140 
 141         static void run() {
 142             execute(ExceptionInInitializerError.class, () -> triggerInitialization(A.class));

 143             ensureFinished();
 144             runTests(); // after initialization is over
 145         }
 146     }
 147 
 148     // ============================================================================================================== //
 149 
 150     static void execute(Class<? extends Throwable> expectedExceptionClass, Runnable action) {
 151         try {
 152             action.run();
 153             if (THROW) throw failure("no exception thrown");
 154         } catch (Throwable e) {
 155             if (THROW) {
 156                 if (e.getClass() == expectedExceptionClass) {
 157                     // expected
 158                 } else {
 159                     String msg = String.format("unexpected exception thrown: expected %s, caught %s",
 160                             expectedExceptionClass.getName(), e);
 161                     throw failure(msg, e);
 162                 }
 163             } else {
 164                 throw failure("no exception expected", e);
 165             }
 166         }
 167     }
 168 
 169     private static AssertionError failure(String msg) {
 170         return new AssertionError(phase + ": " + msg);
 171     }
 172 
 173     private static AssertionError failure(String msg, Throwable e) {
 174         return new AssertionError(phase + ": " + msg, e);
 175     }
 176 
 177     static final List<Thread> BLOCKED_THREADS = Collections.synchronizedList(new ArrayList<>());
 178     static final Consumer<Thread> ON_BLOCK = BLOCKED_THREADS::add;
 179 
 180     static final Map<Thread,Throwable> FAILED_THREADS = Collections.synchronizedMap(new HashMap<>());
 181     static final Thread.UncaughtExceptionHandler ON_FAILURE = FAILED_THREADS::put;
 182 
 183     private static void ensureBlocked() {
 184         for (Thread thr : BLOCKED_THREADS) {
 185             try {
 186                 thr.join(100);
 187                 if (!thr.isAlive()) {
 188                     dump(thr);
 189                     throw new AssertionError("not blocked");
 190                 }
 191             } catch (InterruptedException e) {
 192                 throw new Error(e);
 193             }
 194         }
 195     }
 196 


 284 
 285         final AtomicBoolean cnt = new AtomicBoolean(false);
 286         return () -> {
 287             if (cnt.getAndSet(true)) {
 288                 throw new Error("repeated invocation");
 289             }
 290             invocationCounter.incrementAndGet();
 291             if (phase != validPhase) {
 292                 throw new AssertionError("NON_BLOCKING: wrong phase: " + phase);
 293             }
 294         };
 295     }
 296 
 297     @FunctionalInterface
 298     interface Factory<V> {
 299         V get();
 300     }
 301 
 302     static final AtomicInteger NON_BLOCKING_COUNTER = new AtomicInteger(0);
 303     static final AtomicInteger NON_BLOCKING_ACTIONS = new AtomicInteger(0);
 304     static final Factory<Runnable> NON_BLOCKING = () -> disposableAction(phase, NON_BLOCKING_COUNTER, NON_BLOCKING_ACTIONS);
 305 
 306     static final AtomicInteger BLOCKING_COUNTER = new AtomicInteger(0);
 307     static final AtomicInteger BLOCKING_ACTIONS = new AtomicInteger(0);
 308     static final Factory<Runnable> BLOCKING     = () -> disposableAction(Phase.FINISHED, BLOCKING_COUNTER, BLOCKING_ACTIONS);
 309 
 310     static void checkBlockingAction(TestCase0 r) {
 311         switch (phase) {
 312             case IN_PROGRESS: {
 313                 // Barrier during class initalization.
 314                 r.run(NON_BLOCKING.get());             // initializing thread
 315                 checkBlocked(ON_BLOCK, ON_FAILURE, r); // different thread
 316                 break;
 317             }
 318             case FINISHED: {
 319                 // No barrier after class initalization is over.
 320                 r.run(NON_BLOCKING.get()); // initializing thread
 321                 checkNotBlocked(r);        // different thread
 322                 break;
 323             }
 324             case INIT_FAILURE: {
 325                 // Exception is thrown after class initialization failed.
 326                 TestCase0 test = action -> execute(NoClassDefFoundError.class, () -> r.run(action));
 327 
 328                 test.run(NON_BLOCKING.get()); // initializing thread
 329                 checkNotBlocked(test);        // different thread
 330                 break;
 331             }
 332             default: throw new Error("wrong phase: " + phase);
 333         }
 334     }
 335 
 336     static void checkNonBlockingAction(TestCase0 r) {
 337         r.run(NON_BLOCKING.get()); // initializing thread
 338         checkNotBlocked(r);        // different thread
 339     }
 340 
 341     static <T> void checkNonBlockingAction(T recv, TestCase1<T> r) {
 342         r.run(recv, NON_BLOCKING.get());                  // initializing thread
 343         checkNotBlocked((action) -> r.run(recv, action)); // different thread
 344     }
 345 
 346     static void checkFailingAction(TestCase0 r) {
 347         r.run(NON_BLOCKING.get()); // initializing thread
 348         checkNotBlocked(r);        // different thread
 349     }
 350 
 351     static void triggerInitialization(Class<?> cls) {
 352         try {
 353             Class<?> loadedClass = Class.forName(cls.getName(), true, cls.getClassLoader());
 354             if (loadedClass != cls) {
 355                 throw new Error("wrong class");
 356             }
 357         } catch (ClassNotFoundException e) {
 358             throw new Error(e);
 359         }
 360     }
 361 
 362     static void checkBlocked(Consumer<Thread> onBlockHandler, Thread.UncaughtExceptionHandler onException, TestCase0 r) {
 363         Thread thr = new Thread(() -> {
 364             try {
 365                 r.run(BLOCKING.get());
 366                 System.out.println("Thread " + Thread.currentThread() + ": Finished successfully");
 367             } catch(Throwable e) {
 368                 System.out.println("Thread " + Thread.currentThread() + ": Exception thrown: " + e);
 369                 if (!THROW) {
 370                     e.printStackTrace();


 373             }
 374         } );
 375         thr.setUncaughtExceptionHandler(onException);
 376 
 377         thr.start();
 378         try {
 379             thr.join(100);
 380 
 381             dump(thr);
 382             if (thr.isAlive()) {
 383                 onBlockHandler.accept(thr); // blocked
 384             } else {
 385                 throw new AssertionError("not blocked");
 386             }
 387         } catch (InterruptedException e) {
 388             throw new Error(e);
 389         }
 390     }
 391 
 392     static void checkNotBlocked(TestCase0 r) {
 393         final Thread thr = new Thread(() -> r.run(NON_BLOCKING.get()));
 394         final Throwable[] ex = new Throwable[1];
 395         thr.setUncaughtExceptionHandler((t, e) -> {
 396             if (thr != t) {
 397                 ex[0] = new Error("wrong thread: " + thr + " vs " + t);
 398             } else {
 399                 ex[0] = e;
 400             }
 401         });
 402 
 403         thr.start();
 404         try {
 405             thr.join(15_000);
 406             if (thr.isAlive()) {
 407                 dump(thr);
 408                 throw new AssertionError("blocked");
 409             }
 410         } catch (InterruptedException e) {
 411             throw new Error(e);
 412         }
 413 
 414         if (ex[0] != null) {
 415             throw new AssertionError("no exception expected", ex[0]);
 416         }
 417     }
 418 
 419     static void maybeThrow() {
 420         if (THROW) {
 421             changePhase(Phase.INIT_FAILURE);
 422             throw new RuntimeException("failed class initialization");
 423         }
 424     }
 425 
 426     private static void dump(Thread thr) {
 427         System.out.println("Thread: " + thr);
 428         System.out.println("Thread state: " + thr.getState());
 429         if (thr.isAlive()) {
 430             for (StackTraceElement frame : thr.getStackTrace()) {
 431                 System.out.println(frame);
 432             }
 433         } else {
 434             if (FAILED_THREADS.containsKey(thr)) {
 435                 System.out.println("Failed with an exception: ");


  97         static void testInvokeStaticSync(Runnable action)    { A.staticS(action); }
  98         static void testInvokeStaticNative(Runnable action)  { A.staticN(action); }
  99 
 100         static int  testGetStatic(Runnable action)    { int v = A.staticF; action.run(); return v;   }
 101         static void testPutStatic(Runnable action)    { A.staticF = 1;     action.run(); }
 102         static A    testNewInstanceA(Runnable action) { A obj = new A();   action.run(); return obj; }
 103         static B    testNewInstanceB(Runnable action) { B obj = new B();   action.run(); return obj; }
 104 
 105         static int  testGetField(A recv, Runnable action)      { int v = recv.f; action.run(); return v; }
 106         static void testPutField(A recv, Runnable action)      { recv.f = 1;     action.run(); }
 107         static void testInvokeVirtual(A recv, Runnable action) { recv.m();       action.run(); }
 108 
 109         static void runTests() {
 110             checkBlockingAction(Test::testInvokeStatic);       // invokestatic
 111             checkBlockingAction(Test::testInvokeStaticNative); // invokestatic
 112             checkBlockingAction(Test::testInvokeStaticSync);   // invokestatic
 113             checkBlockingAction(Test::testGetStatic);          // getstatic
 114             checkBlockingAction(Test::testPutStatic);          // putstatic
 115             checkBlockingAction(Test::testNewInstanceA);       // new
 116 
 117             A recv = testNewInstanceB(NON_BLOCKING.get()); // trigger B initialization
 118             checkNonBlockingAction(Test::testNewInstanceB); // new: NO BLOCKING: same thread: A being initialized, B fully initialized
 119 
 120             checkNonBlockingAction(recv, Test::testGetField);      // getfield
 121             checkNonBlockingAction(recv, Test::testPutField);      // putfield
 122             checkNonBlockingAction(recv, Test::testInvokeVirtual); // invokevirtual
 123         }
 124 
 125         static void warmup() {
 126             for (int i = 0; i < 20_000; i++) {
 127                 testInvokeStatic(      NON_BLOCKING_WARMUP);
 128                 testInvokeStaticNative(NON_BLOCKING_WARMUP);
 129                 testInvokeStaticSync(  NON_BLOCKING_WARMUP);
 130                 testGetStatic(         NON_BLOCKING_WARMUP);
 131                 testPutStatic(         NON_BLOCKING_WARMUP);
 132                 testNewInstanceA(      NON_BLOCKING_WARMUP);
 133                 testNewInstanceB(      NON_BLOCKING_WARMUP);
 134 
 135                 testGetField(new B(),      NON_BLOCKING_WARMUP);
 136                 testPutField(new B(),      NON_BLOCKING_WARMUP);
 137                 testInvokeVirtual(new B(), NON_BLOCKING_WARMUP);
 138             }
 139         }
 140 
 141         static void run() {
 142             execute(ExceptionInInitializerError.class, () -> triggerInitialization(A.class));
 143 
 144             ensureFinished();

 145         }
 146     }
 147 
 148     // ============================================================================================================== //
 149 
 150     static void execute(Class<? extends Throwable> expectedExceptionClass, Runnable action) {
 151         try {
 152             action.run();
 153             if (THROW)  throw new AssertionError("no exception thrown");
 154         } catch (Throwable e) {
 155             if (THROW) {
 156                 if (e.getClass() == expectedExceptionClass) {
 157                     // expected
 158                 } else {
 159                     String msg = String.format("unexpected exception thrown: expected %s, caught %s",
 160                             expectedExceptionClass.getName(), e.getClass().getName());
 161                     throw new AssertionError(msg, e);
 162                 }
 163             } else {
 164                 throw new AssertionError("no exception expected", e);
 165             }
 166         }
 167     }
 168 








 169     static final List<Thread> BLOCKED_THREADS = Collections.synchronizedList(new ArrayList<>());
 170     static final Consumer<Thread> ON_BLOCK = BLOCKED_THREADS::add;
 171 
 172     static final Map<Thread,Throwable> FAILED_THREADS = Collections.synchronizedMap(new HashMap<>());
 173     static final Thread.UncaughtExceptionHandler ON_FAILURE = FAILED_THREADS::put;
 174 
 175     private static void ensureBlocked() {
 176         for (Thread thr : BLOCKED_THREADS) {
 177             try {
 178                 thr.join(100);
 179                 if (!thr.isAlive()) {
 180                     dump(thr);
 181                     throw new AssertionError("not blocked");
 182                 }
 183             } catch (InterruptedException e) {
 184                 throw new Error(e);
 185             }
 186         }
 187     }
 188 


 276 
 277         final AtomicBoolean cnt = new AtomicBoolean(false);
 278         return () -> {
 279             if (cnt.getAndSet(true)) {
 280                 throw new Error("repeated invocation");
 281             }
 282             invocationCounter.incrementAndGet();
 283             if (phase != validPhase) {
 284                 throw new AssertionError("NON_BLOCKING: wrong phase: " + phase);
 285             }
 286         };
 287     }
 288 
 289     @FunctionalInterface
 290     interface Factory<V> {
 291         V get();
 292     }
 293 
 294     static final AtomicInteger NON_BLOCKING_COUNTER = new AtomicInteger(0);
 295     static final AtomicInteger NON_BLOCKING_ACTIONS = new AtomicInteger(0);
 296     static final Factory<Runnable> NON_BLOCKING = () -> disposableAction(Phase.IN_PROGRESS, NON_BLOCKING_COUNTER, NON_BLOCKING_ACTIONS);
 297 
 298     static final AtomicInteger BLOCKING_COUNTER = new AtomicInteger(0);
 299     static final AtomicInteger BLOCKING_ACTIONS = new AtomicInteger(0);
 300     static final Factory<Runnable> BLOCKING     = () -> disposableAction(Phase.FINISHED, BLOCKING_COUNTER, BLOCKING_ACTIONS);
 301 
 302     static void checkBlockingAction(TestCase0 r) {
 303         r.run(NON_BLOCKING.get()); // same thread
 304         checkBlocked(ON_BLOCK, ON_FAILURE, r); // different thread





















 305     }
 306 
 307     static void checkNonBlockingAction(TestCase0 r) {
 308         r.run(NON_BLOCKING.get());
 309         checkNotBlocked(r); // different thread
 310     }
 311 
 312     static <T> void checkNonBlockingAction(T recv, TestCase1<T> r) {
 313         r.run(recv, NON_BLOCKING.get()); // same thread
 314         checkNotBlocked((action) -> r.run(recv, action)); // different thread
 315     }
 316 





 317     static void triggerInitialization(Class<?> cls) {
 318         try {
 319             Class<?> loadedClass = Class.forName(cls.getName(), true, cls.getClassLoader());
 320             if (loadedClass != cls) {
 321                 throw new Error("wrong class");
 322             }
 323         } catch (ClassNotFoundException e) {
 324             throw new Error(e);
 325         }
 326     }
 327 
 328     static void checkBlocked(Consumer<Thread> onBlockHandler, Thread.UncaughtExceptionHandler onException, TestCase0 r) {
 329         Thread thr = new Thread(() -> {
 330             try {
 331                 r.run(BLOCKING.get());
 332                 System.out.println("Thread " + Thread.currentThread() + ": Finished successfully");
 333             } catch(Throwable e) {
 334                 System.out.println("Thread " + Thread.currentThread() + ": Exception thrown: " + e);
 335                 if (!THROW) {
 336                     e.printStackTrace();


 339             }
 340         } );
 341         thr.setUncaughtExceptionHandler(onException);
 342 
 343         thr.start();
 344         try {
 345             thr.join(100);
 346 
 347             dump(thr);
 348             if (thr.isAlive()) {
 349                 onBlockHandler.accept(thr); // blocked
 350             } else {
 351                 throw new AssertionError("not blocked");
 352             }
 353         } catch (InterruptedException e) {
 354             throw new Error(e);
 355         }
 356     }
 357 
 358     static void checkNotBlocked(TestCase0 r) {
 359         Thread thr = new Thread(() -> r.run(NON_BLOCKING.get()));








 360 
 361         thr.start();
 362         try {
 363             thr.join(15_000);
 364             if (thr.isAlive()) {
 365                 dump(thr);
 366                 throw new AssertionError("blocked");
 367             }
 368         } catch (InterruptedException e) {
 369             throw new Error(e);




 370         }
 371     }
 372 
 373     static void maybeThrow() {
 374         if (THROW) {
 375             changePhase(Phase.INIT_FAILURE);
 376             throw new RuntimeException("failed class initialization");
 377         }
 378     }
 379 
 380     private static void dump(Thread thr) {
 381         System.out.println("Thread: " + thr);
 382         System.out.println("Thread state: " + thr.getState());
 383         if (thr.isAlive()) {
 384             for (StackTraceElement frame : thr.getStackTrace()) {
 385                 System.out.println(frame);
 386             }
 387         } else {
 388             if (FAILED_THREADS.containsKey(thr)) {
 389                 System.out.println("Failed with an exception: ");
< prev index next >