< prev index next >

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

Print this page

  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  */
 23 
 24 /*
 25  * @test
 26  * @library /test/lib
 27  *
 28  * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -Xint                   -DTHROW=false -Xcheck:jni ClassInitBarrier
 29  * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -Xint                   -DTHROW=true  -Xcheck:jni ClassInitBarrier
 30  *
 31  * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:TieredStopAtLevel=1 -DTHROW=false -Xcheck:jni ClassInitBarrier
 32  * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:TieredStopAtLevel=1 -DTHROW=true  -Xcheck:jni ClassInitBarrier
 33  *
 34  * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:-TieredCompilation  -DTHROW=false -Xcheck:jni ClassInitBarrier
 35  * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:-TieredCompilation  -DTHROW=true  -Xcheck:jni ClassInitBarrier
 36  *
 37  * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:TieredStopAtLevel=1 -DTHROW=false -XX:CompileCommand=dontinline,*::static* -Xcheck:jni ClassInitBarrier
 38  * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:TieredStopAtLevel=1 -DTHROW=true  -XX:CompileCommand=dontinline,*::static* -Xcheck:jni ClassInitBarrier
 39  * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:-TieredCompilation  -DTHROW=false -XX:CompileCommand=dontinline,*::static* -Xcheck:jni ClassInitBarrier
 40  * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:-TieredCompilation  -DTHROW=true  -XX:CompileCommand=dontinline,*::static* -Xcheck:jni ClassInitBarrier
 41  *
 42  * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:TieredStopAtLevel=1 -DTHROW=false -XX:CompileCommand=exclude,*::static* -Xcheck:jni ClassInitBarrier
 43  * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:TieredStopAtLevel=1 -DTHROW=true  -XX:CompileCommand=exclude,*::static* -Xcheck:jni ClassInitBarrier
 44  * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:-TieredCompilation  -DTHROW=false -XX:CompileCommand=exclude,*::static* -Xcheck:jni ClassInitBarrier
 45  * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:-TieredCompilation  -DTHROW=true  -XX:CompileCommand=exclude,*::static* -Xcheck:jni ClassInitBarrier
 46  */
 47 
 48 import jdk.test.lib.Asserts;
 49 
 50 import java.util.*;
 51 import java.util.concurrent.atomic.AtomicBoolean;
 52 import java.util.concurrent.atomic.AtomicInteger;
 53 import java.util.function.Consumer;
 54 
 55 public class ClassInitBarrier {
 56     static {
 57         System.loadLibrary("ClassInitBarrier");
 58 
 59         if (!init()) {
 60             throw new Error("init failed");
 61         }
 62     }
 63 
 64     static native boolean init();
 65 
 66     static final boolean THROW = Boolean.getBoolean("THROW");
 67 








 68     static class Test {

 69         static class A {
 70             static {
 71                 if (!init(B.class)) {
 72                     throw new Error("init failed");
 73                 }
 74 
 75                 changePhase(Phase.IN_PROGRESS);
 76                 runTests();      // interpreted mode
 77                 warmup();        // trigger compilation
 78                 runTests();      // compiled mode
 79 
 80                 ensureBlocked(); // ensure still blocked
 81                 maybeThrow();    // fail initialization if needed
 82 
 83                 changePhase(Phase.FINISHED);
 84             }
 85 
 86             static              void staticM(Runnable action) { action.run(); }
 87             static synchronized void staticS(Runnable action) { action.run(); }
 88             static native       void staticN(Runnable action);
 89 
 90             static int staticF;
 91 
 92             int f;
 93             void m() {}
 94 
 95             static native boolean init(Class<B> cls);
 96         }
 97 
 98         static class B extends A {}
 99 
100         static void testInvokeStatic(Runnable action)       { A.staticM(action); }
101         static void testInvokeStaticSync(Runnable action)   { A.staticS(action); }
102         static void testInvokeStaticNative(Runnable action) { A.staticN(action); }
103 
104         static int  testGetStatic(Runnable action)    { int v = A.staticF; action.run(); return v;   }
105         static void testPutStatic(Runnable action)    { A.staticF = 1;     action.run(); }
106         static A    testNewInstanceA(Runnable action) { A obj = new A();   action.run(); return obj; }
107         static B    testNewInstanceB(Runnable action) { B obj = new B();   action.run(); return obj; }
108 
109         static int  testGetField(A recv, Runnable action)      { int v = recv.f; action.run(); return v; }
110         static void testPutField(A recv, Runnable action)      { recv.f = 1;     action.run(); }
111         static void testInvokeVirtual(A recv, Runnable action) { recv.m();       action.run(); }
112 
113         static native void testInvokeStaticJNI(Runnable action);
114         static native void testInvokeStaticSyncJNI(Runnable action);
115         static native void testInvokeStaticNativeJNI(Runnable action);
116 
117         static native int  testGetStaticJNI(Runnable action);
118         static native void testPutStaticJNI(Runnable action);
119         static native A    testNewInstanceAJNI(Runnable action);
120         static native B    testNewInstanceBJNI(Runnable action);
121 
122         static native int  testGetFieldJNI(A recv, Runnable action);
123         static native void testPutFieldJNI(A recv, Runnable action);
124         static native void testInvokeVirtualJNI(A recv, Runnable action);
125 
126         static void runTests() {
127             checkBlockingAction(Test::testInvokeStatic);       // invokestatic
128             checkBlockingAction(Test::testInvokeStaticSync);   // invokestatic
129             checkBlockingAction(Test::testInvokeStaticNative); // invokestatic
130             checkBlockingAction(Test::testGetStatic);          // getstatic
131             checkBlockingAction(Test::testPutStatic);          // putstatic
132             checkBlockingAction(Test::testNewInstanceA);       // new
133 
134             checkNonBlockingAction(Test::testInvokeStaticJNI);       // invokestatic
135             checkNonBlockingAction(Test::testInvokeStaticSyncJNI);   // invokestatic
136             checkNonBlockingAction(Test::testInvokeStaticNativeJNI); // invokestatic
137             checkNonBlockingAction(Test::testGetStaticJNI);          // getstatic
138             checkNonBlockingAction(Test::testPutStaticJNI);          // putstatic
139             checkBlockingAction(Test::testNewInstanceAJNI);          // new
140 
141             A recv = testNewInstanceB(NON_BLOCKING.get());  // trigger B initialization
142             checkNonBlockingAction(Test::testNewInstanceB); // new: NO BLOCKING: same thread: A being initialized, B fully initialized
143 
144             checkNonBlockingAction(recv, Test::testGetField);      // getfield
145             checkNonBlockingAction(recv, Test::testPutField);      // putfield
146             checkNonBlockingAction(recv, Test::testInvokeVirtual); // invokevirtual
147 
148             checkNonBlockingAction(Test::testNewInstanceBJNI);        // new: NO BLOCKING: same thread: A being initialized, B fully initialized
149             checkNonBlockingAction(recv, Test::testGetFieldJNI);      // getfield
150             checkNonBlockingAction(recv, Test::testPutFieldJNI);      // putfield
151             checkNonBlockingAction(recv, Test::testInvokeVirtualJNI); // invokevirtual
152         }
153 
154         static void warmup() {

155             for (int i = 0; i < 20_000; i++) {
156                 testInvokeStatic(      NON_BLOCKING_WARMUP);
157                 testInvokeStaticNative(NON_BLOCKING_WARMUP);
158                 testInvokeStaticSync(  NON_BLOCKING_WARMUP);
159                 testGetStatic(         NON_BLOCKING_WARMUP);
160                 testPutStatic(         NON_BLOCKING_WARMUP);
161                 testNewInstanceA(      NON_BLOCKING_WARMUP);
162                 testNewInstanceB(      NON_BLOCKING_WARMUP);
163 
164                 testGetField(new B(),      NON_BLOCKING_WARMUP);
165                 testPutField(new B(),      NON_BLOCKING_WARMUP);
166                 testInvokeVirtual(new B(), NON_BLOCKING_WARMUP);
167             }
168         }
169 
170         static void run() {
171             execute(ExceptionInInitializerError.class, () -> triggerInitialization(A.class));
172             ensureFinished();
173             runTests(); // after initialization is over
174         }
175     }
176 
177     // ============================================================================================================== //
178 
179     static void execute(Class<? extends Throwable> expectedExceptionClass, Runnable action) {
180         try {
181             action.run();
182             if (THROW) throw failure("no exception thrown");
183         } catch (Throwable e) {
184             if (THROW) {
185                 if (e.getClass() == expectedExceptionClass) {
186                     // expected

246                 if (ex.getClass() != NoClassDefFoundError.class) {
247                     throw new AssertionError(thr + ": wrong exception thrown", ex);
248                 }
249             } else {
250                 if (FAILED_THREADS.containsKey(thr)) {
251                     Throwable ex = FAILED_THREADS.get(thr);
252                     throw new AssertionError(thr + ": exception thrown", ex);
253                 }
254             }
255         }
256         if (THROW) {
257             Asserts.assertEquals(BLOCKING_COUNTER.get(), 0);
258         } else {
259             Asserts.assertEquals(BLOCKING_COUNTER.get(), BLOCKING_ACTIONS.get());
260         }
261 
262         dumpInfo();
263     }
264 
265     interface TestCase0 {
266         void run(Runnable runnable);
267     }
268 
269     interface TestCase1<T> {
270         void run(T arg, Runnable runnable);
271     }
272 
273     enum Phase { BEFORE_INIT, IN_PROGRESS, FINISHED, INIT_FAILURE }
274 
275     static volatile Phase phase = Phase.BEFORE_INIT;
276 
277     static void changePhase(Phase newPhase) {
278         dumpInfo();
279 
280         Phase oldPhase = phase;
281         switch (oldPhase) {
282             case BEFORE_INIT:
283                 Asserts.assertEquals(NON_BLOCKING_ACTIONS.get(), 0);
284                 Asserts.assertEquals(NON_BLOCKING_COUNTER.get(), 0);
285 
286                 Asserts.assertEquals(BLOCKING_ACTIONS.get(),     0);
287                 Asserts.assertEquals(BLOCKING_COUNTER.get(),     0);
288                 break;
289             case IN_PROGRESS:
290                 Asserts.assertEquals(NON_BLOCKING_COUNTER.get(), NON_BLOCKING_ACTIONS.get());

320             if (phase != validPhase) {
321                 throw new AssertionError("NON_BLOCKING: wrong phase: " + phase);
322             }
323         };
324     }
325 
326     @FunctionalInterface
327     interface Factory<V> {
328         V get();
329     }
330 
331     static final AtomicInteger NON_BLOCKING_COUNTER = new AtomicInteger(0);
332     static final AtomicInteger NON_BLOCKING_ACTIONS = new AtomicInteger(0);
333     static final Factory<Runnable> NON_BLOCKING = () -> disposableAction(phase, NON_BLOCKING_COUNTER, NON_BLOCKING_ACTIONS);
334 
335     static final AtomicInteger BLOCKING_COUNTER = new AtomicInteger(0);
336     static final AtomicInteger BLOCKING_ACTIONS = new AtomicInteger(0);
337     static final Factory<Runnable> BLOCKING     = () -> disposableAction(Phase.FINISHED, BLOCKING_COUNTER, BLOCKING_ACTIONS);
338 
339     static void checkBlockingAction(TestCase0 r) {

340         switch (phase) {
341             case IN_PROGRESS: {
342                 // Barrier during class initalization.
343                 r.run(NON_BLOCKING.get());             // initializing thread
344                 checkBlocked(ON_BLOCK, ON_FAILURE, r); // different thread
345                 break;
346             }
347             case FINISHED: {
348                 // No barrier after class initalization is over.
349                 r.run(NON_BLOCKING.get()); // initializing thread
350                 checkNotBlocked(r);        // different thread
351                 break;
352             }
353             case INIT_FAILURE: {
354                 // Exception is thrown after class initialization failed.
355                 TestCase0 test = action -> execute(NoClassDefFoundError.class, () -> r.run(action));
356 
357                 test.run(NON_BLOCKING.get()); // initializing thread
358                 checkNotBlocked(test);        // different thread
359                 break;
360             }
361             default: throw new Error("wrong phase: " + phase);
362         }
363     }
364 
365     static void checkNonBlockingAction(TestCase0 r) {
366         r.run(NON_BLOCKING.get()); // initializing thread
367         checkNotBlocked(r);        // different thread
368     }
369 
370     static <T> void checkNonBlockingAction(T recv, TestCase1<T> r) {
371         r.run(recv, NON_BLOCKING.get());                  // initializing thread
372         checkNotBlocked((action) -> r.run(recv, action)); // different thread
373     }
374 
375     static void checkFailingAction(TestCase0 r) {
376         r.run(NON_BLOCKING.get()); // initializing thread
377         checkNotBlocked(r);        // different thread
378     }
379 
380     static void triggerInitialization(Class<?> cls) {
381         try {
382             Class<?> loadedClass = Class.forName(cls.getName(), true, cls.getClassLoader());
383             if (loadedClass != cls) {
384                 throw new Error("wrong class");
385             }
386         } catch (ClassNotFoundException e) {
387             throw new Error(e);
388         }
389     }
390 
391     static void checkBlocked(Consumer<Thread> onBlockHandler, Thread.UncaughtExceptionHandler onException, TestCase0 r) {
392         Thread thr = new Thread(() -> {
393             try {
394                 r.run(BLOCKING.get());
395                 System.out.println("Thread " + Thread.currentThread() + ": Finished successfully");
396             } catch(Throwable e) {
397                 System.out.println("Thread " + Thread.currentThread() + ": Exception thrown: " + e);
398                 if (!THROW) {
399                     e.printStackTrace();
400                 }
401                 throw e;
402             }
403         } );
404         thr.setUncaughtExceptionHandler(onException);
405 
406         thr.start();
407         try {
408             thr.join(100);
409 
410             dump(thr);
411             if (thr.isAlive()) {
412                 onBlockHandler.accept(thr); // blocked
413             } else {
414                 throw new AssertionError("not blocked");
415             }
416         } catch (InterruptedException e) {
417             throw new Error(e);
418         }
419     }
420 
421     static void checkNotBlocked(TestCase0 r) {
422         final Thread thr = new Thread(() -> r.run(NON_BLOCKING.get()));
423         final Throwable[] ex = new Throwable[1];
424         thr.setUncaughtExceptionHandler((t, e) -> {
425             if (thr != t) {
426                 ex[0] = new Error("wrong thread: " + thr + " vs " + t);
427             } else {
428                 ex[0] = e;
429             }
430         });
431 
432         thr.start();
433         try {
434             thr.join(15_000);
435             if (thr.isAlive()) {
436                 dump(thr);
437                 throw new AssertionError("blocked");
438             }
439         } catch (InterruptedException e) {
440             throw new Error(e);
441         }
442 

  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  */
 23 
 24 /*
 25  * @test
 26  * @library /test/lib
 27  *
 28  * @enablePreview




 29  *
 30  * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:-TieredCompilation  -DTHROW=false -Xcheck:jni ClassInitBarrier
 31  * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:-TieredCompilation  -DTHROW=true  -Xcheck:jni ClassInitBarrier
 32  *
 33  * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:TieredStopAtLevel=1 -DTHROW=false -XX:CompileCommand=dontinline,*::static* -Xcheck:jni ClassInitBarrier
 34  * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:TieredStopAtLevel=1 -DTHROW=true  -XX:CompileCommand=dontinline,*::static* -Xcheck:jni ClassInitBarrier
 35  * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:-TieredCompilation  -DTHROW=false -XX:CompileCommand=dontinline,*::static* -Xcheck:jni ClassInitBarrier
 36  * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:-TieredCompilation  -DTHROW=true  -XX:CompileCommand=dontinline,*::static* -Xcheck:jni ClassInitBarrier
 37  *
 38  * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:TieredStopAtLevel=1 -DTHROW=false -XX:CompileCommand=exclude,*::static* -Xcheck:jni ClassInitBarrier
 39  * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:TieredStopAtLevel=1 -DTHROW=true  -XX:CompileCommand=exclude,*::static* -Xcheck:jni ClassInitBarrier
 40  * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:-TieredCompilation  -DTHROW=false -XX:CompileCommand=exclude,*::static* -Xcheck:jni ClassInitBarrier
 41  * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:-TieredCompilation  -DTHROW=true  -XX:CompileCommand=exclude,*::static* -Xcheck:jni ClassInitBarrier
 42  */
 43 
 44 import jdk.test.lib.Asserts;
 45 
 46 import java.util.*;
 47 import java.util.concurrent.atomic.AtomicBoolean;
 48 import java.util.concurrent.atomic.AtomicInteger;
 49 import java.util.function.Consumer;
 50 
 51 public class ClassInitBarrier {
 52     static {
 53         System.loadLibrary("ClassInitBarrier");
 54 
 55         if (!init()) {
 56             throw new Error("init failed");
 57         }
 58     }
 59 
 60     static native boolean init();
 61 
 62     static final boolean THROW = Boolean.getBoolean("THROW");
 63 
 64     static value class MyValue {
 65         int x = 42;
 66 
 67         void verify() {
 68             Asserts.assertEquals(x, 42);
 69         }
 70     }
 71 
 72     static class Test {
 73 
 74         static class A {
 75             static {
 76                 if (!init(B.class)) {
 77                     throw new Error("init failed");
 78                 }
 79 
 80                 changePhase(Phase.IN_PROGRESS);
 81                 runTests();      // interpreted mode
 82                 warmup();        // trigger compilation
 83                 runTests();      // compiled mode
 84 
 85                 ensureBlocked(); // ensure still blocked
 86                 maybeThrow();    // fail initialization if needed
 87 
 88                 changePhase(Phase.FINISHED);
 89             }
 90 
 91             static              void staticM(Runnable action, MyValue val) { action.run(); val.verify(); }
 92             static synchronized void staticS(Runnable action, MyValue val) { action.run(); val.verify(); }
 93             static native       void staticN(Runnable action, MyValue val);
 94 
 95             static int staticF;
 96 
 97             int f;
 98             void m() {}
 99 
100             static native boolean init(Class<B> cls);
101         }
102 
103         static class B extends A {}
104 
105         static void testInvokeStatic(Runnable action, MyValue val)       { A.staticM(action, val); }
106         static void testInvokeStaticSync(Runnable action, MyValue val)   { A.staticS(action, val); }
107         static void testInvokeStaticNative(Runnable action, MyValue val) { A.staticN(action, val); }
108 
109         static int  testGetStatic(Runnable action, MyValue val)    { int v = A.staticF; action.run(); val.verify(); return v;   }
110         static void testPutStatic(Runnable action, MyValue val)    { A.staticF = 1;     action.run(); val.verify(); }
111         static A    testNewInstanceA(Runnable action, MyValue val) { A obj = new A();   action.run(); val.verify(); return obj; }
112         static B    testNewInstanceB(Runnable action, MyValue val) { B obj = new B();   action.run(); val.verify(); return obj; }
113 
114         static int  testGetField(A recv, Runnable action, MyValue val)      { int v = recv.f; action.run(); val.verify(); return v; }
115         static void testPutField(A recv, Runnable action, MyValue val)      { recv.f = 1;     action.run(); val.verify(); }
116         static void testInvokeVirtual(A recv, Runnable action, MyValue val) { recv.m();       action.run(); val.verify(); }
117 
118         static native void testInvokeStaticJNI(Runnable action, MyValue val);
119         static native void testInvokeStaticSyncJNI(Runnable action, MyValue val);
120         static native void testInvokeStaticNativeJNI(Runnable action, MyValue val);
121 
122         static native int  testGetStaticJNI(Runnable action, MyValue val);
123         static native void testPutStaticJNI(Runnable action, MyValue val);
124         static native A    testNewInstanceAJNI(Runnable action, MyValue val);
125         static native B    testNewInstanceBJNI(Runnable action, MyValue val);
126 
127         static native int  testGetFieldJNI(A recv, Runnable action, MyValue val);
128         static native void testPutFieldJNI(A recv, Runnable action, MyValue val);
129         static native void testInvokeVirtualJNI(A recv, Runnable action, MyValue val);
130 
131         static void runTests() {
132             checkBlockingAction(Test::testInvokeStatic);       // invokestatic
133             checkBlockingAction(Test::testInvokeStaticSync);   // invokestatic
134             checkBlockingAction(Test::testInvokeStaticNative); // invokestatic
135             checkBlockingAction(Test::testGetStatic);          // getstatic
136             checkBlockingAction(Test::testPutStatic);          // putstatic
137             checkBlockingAction(Test::testNewInstanceA);       // new
138 
139             checkNonBlockingAction(Test::testInvokeStaticJNI);       // invokestatic
140             checkNonBlockingAction(Test::testInvokeStaticSyncJNI);   // invokestatic
141             checkNonBlockingAction(Test::testInvokeStaticNativeJNI); // invokestatic
142             checkNonBlockingAction(Test::testGetStaticJNI);          // getstatic
143             checkNonBlockingAction(Test::testPutStaticJNI);          // putstatic
144             checkBlockingAction(Test::testNewInstanceAJNI);          // new
145 
146             A recv = testNewInstanceB(NON_BLOCKING.get(), new MyValue());  // trigger B initialization
147             checkNonBlockingAction(Test::testNewInstanceB); // new: NO BLOCKING: same thread: A being initialized, B fully initialized
148 
149             checkNonBlockingAction(recv, Test::testGetField);      // getfield
150             checkNonBlockingAction(recv, Test::testPutField);      // putfield
151             checkNonBlockingAction(recv, Test::testInvokeVirtual); // invokevirtual
152 
153             checkNonBlockingAction(Test::testNewInstanceBJNI);        // new: NO BLOCKING: same thread: A being initialized, B fully initialized
154             checkNonBlockingAction(recv, Test::testGetFieldJNI);      // getfield
155             checkNonBlockingAction(recv, Test::testPutFieldJNI);      // putfield
156             checkNonBlockingAction(recv, Test::testInvokeVirtualJNI); // invokevirtual
157         }
158 
159         static void warmup() {
160             MyValue val = new MyValue();
161             for (int i = 0; i < 20_000; i++) {
162                 testInvokeStatic(      NON_BLOCKING_WARMUP, val);
163                 testInvokeStaticNative(NON_BLOCKING_WARMUP, val);
164                 testInvokeStaticSync(  NON_BLOCKING_WARMUP, val);
165                 testGetStatic(         NON_BLOCKING_WARMUP, val);
166                 testPutStatic(         NON_BLOCKING_WARMUP, val);
167                 testNewInstanceA(      NON_BLOCKING_WARMUP, val);
168                 testNewInstanceB(      NON_BLOCKING_WARMUP, val);
169 
170                 testGetField(new B(),      NON_BLOCKING_WARMUP, val);
171                 testPutField(new B(),      NON_BLOCKING_WARMUP, val);
172                 testInvokeVirtual(new B(), NON_BLOCKING_WARMUP, val);
173             }
174         }
175 
176         static void run() {
177             execute(ExceptionInInitializerError.class, () -> triggerInitialization(A.class));
178             ensureFinished();
179             runTests(); // after initialization is over
180         }
181     }
182 
183     // ============================================================================================================== //
184 
185     static void execute(Class<? extends Throwable> expectedExceptionClass, Runnable action) {
186         try {
187             action.run();
188             if (THROW) throw failure("no exception thrown");
189         } catch (Throwable e) {
190             if (THROW) {
191                 if (e.getClass() == expectedExceptionClass) {
192                     // expected

252                 if (ex.getClass() != NoClassDefFoundError.class) {
253                     throw new AssertionError(thr + ": wrong exception thrown", ex);
254                 }
255             } else {
256                 if (FAILED_THREADS.containsKey(thr)) {
257                     Throwable ex = FAILED_THREADS.get(thr);
258                     throw new AssertionError(thr + ": exception thrown", ex);
259                 }
260             }
261         }
262         if (THROW) {
263             Asserts.assertEquals(BLOCKING_COUNTER.get(), 0);
264         } else {
265             Asserts.assertEquals(BLOCKING_COUNTER.get(), BLOCKING_ACTIONS.get());
266         }
267 
268         dumpInfo();
269     }
270 
271     interface TestCase0 {
272         void run(Runnable runnable, MyValue val);
273     }
274 
275     interface TestCase1<T> {
276         void run(T arg, Runnable runnable, MyValue val);
277     }
278 
279     enum Phase { BEFORE_INIT, IN_PROGRESS, FINISHED, INIT_FAILURE }
280 
281     static volatile Phase phase = Phase.BEFORE_INIT;
282 
283     static void changePhase(Phase newPhase) {
284         dumpInfo();
285 
286         Phase oldPhase = phase;
287         switch (oldPhase) {
288             case BEFORE_INIT:
289                 Asserts.assertEquals(NON_BLOCKING_ACTIONS.get(), 0);
290                 Asserts.assertEquals(NON_BLOCKING_COUNTER.get(), 0);
291 
292                 Asserts.assertEquals(BLOCKING_ACTIONS.get(),     0);
293                 Asserts.assertEquals(BLOCKING_COUNTER.get(),     0);
294                 break;
295             case IN_PROGRESS:
296                 Asserts.assertEquals(NON_BLOCKING_COUNTER.get(), NON_BLOCKING_ACTIONS.get());

326             if (phase != validPhase) {
327                 throw new AssertionError("NON_BLOCKING: wrong phase: " + phase);
328             }
329         };
330     }
331 
332     @FunctionalInterface
333     interface Factory<V> {
334         V get();
335     }
336 
337     static final AtomicInteger NON_BLOCKING_COUNTER = new AtomicInteger(0);
338     static final AtomicInteger NON_BLOCKING_ACTIONS = new AtomicInteger(0);
339     static final Factory<Runnable> NON_BLOCKING = () -> disposableAction(phase, NON_BLOCKING_COUNTER, NON_BLOCKING_ACTIONS);
340 
341     static final AtomicInteger BLOCKING_COUNTER = new AtomicInteger(0);
342     static final AtomicInteger BLOCKING_ACTIONS = new AtomicInteger(0);
343     static final Factory<Runnable> BLOCKING     = () -> disposableAction(Phase.FINISHED, BLOCKING_COUNTER, BLOCKING_ACTIONS);
344 
345     static void checkBlockingAction(TestCase0 r) {
346         MyValue val = new MyValue();
347         switch (phase) {
348             case IN_PROGRESS: {
349                 // Barrier during class initalization.
350                 r.run(NON_BLOCKING.get(), val);             // initializing thread
351                 checkBlocked(ON_BLOCK, ON_FAILURE, r); // different thread
352                 break;
353             }
354             case FINISHED: {
355                 // No barrier after class initalization is over.
356                 r.run(NON_BLOCKING.get(), val); // initializing thread
357                 checkNotBlocked(r);        // different thread
358                 break;
359             }
360             case INIT_FAILURE: {
361                 // Exception is thrown after class initialization failed.
362                 TestCase0 test = (action, valarg) -> execute(NoClassDefFoundError.class, () -> r.run(action, valarg));
363 
364                 test.run(NON_BLOCKING.get(), val); // initializing thread
365                 checkNotBlocked(test);        // different thread
366                 break;
367             }
368             default: throw new Error("wrong phase: " + phase);
369         }
370     }
371 
372     static void checkNonBlockingAction(TestCase0 r) {
373         r.run(NON_BLOCKING.get(), new MyValue()); // initializing thread
374         checkNotBlocked(r);        // different thread
375     }
376 
377     static <T> void checkNonBlockingAction(T recv, TestCase1<T> r) {
378         r.run(recv, NON_BLOCKING.get(), new MyValue());                  // initializing thread
379         checkNotBlocked((action, val) -> r.run(recv, action, val)); // different thread
380     }
381 
382     static void checkFailingAction(TestCase0 r) {
383         r.run(NON_BLOCKING.get(), new MyValue()); // initializing thread
384         checkNotBlocked(r);        // different thread
385     }
386 
387     static void triggerInitialization(Class<?> cls) {
388         try {
389             Class<?> loadedClass = Class.forName(cls.getName(), true, cls.getClassLoader());
390             if (loadedClass != cls) {
391                 throw new Error("wrong class");
392             }
393         } catch (ClassNotFoundException e) {
394             throw new Error(e);
395         }
396     }
397 
398     static void checkBlocked(Consumer<Thread> onBlockHandler, Thread.UncaughtExceptionHandler onException, TestCase0 r) {
399         Thread thr = new Thread(() -> {
400             try {
401                 r.run(BLOCKING.get(), new MyValue());
402                 System.out.println("Thread " + Thread.currentThread() + ": Finished successfully");
403             } catch(Throwable e) {
404                 System.out.println("Thread " + Thread.currentThread() + ": Exception thrown: " + e);
405                 if (!THROW) {
406                     e.printStackTrace();
407                 }
408                 throw e;
409             }
410         } );
411         thr.setUncaughtExceptionHandler(onException);
412 
413         thr.start();
414         try {
415             thr.join(100);
416 
417             dump(thr);
418             if (thr.isAlive()) {
419                 onBlockHandler.accept(thr); // blocked
420             } else {
421                 throw new AssertionError("not blocked");
422             }
423         } catch (InterruptedException e) {
424             throw new Error(e);
425         }
426     }
427 
428     static void checkNotBlocked(TestCase0 r) {
429         final Thread thr = new Thread(() -> r.run(NON_BLOCKING.get(), new MyValue()));
430         final Throwable[] ex = new Throwable[1];
431         thr.setUncaughtExceptionHandler((t, e) -> {
432             if (thr != t) {
433                 ex[0] = new Error("wrong thread: " + thr + " vs " + t);
434             } else {
435                 ex[0] = e;
436             }
437         });
438 
439         thr.start();
440         try {
441             thr.join(15_000);
442             if (thr.isAlive()) {
443                 dump(thr);
444                 throw new AssertionError("blocked");
445             }
446         } catch (InterruptedException e) {
447             throw new Error(e);
448         }
449 
< prev index next >