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 }
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: ");
390 FAILED_THREADS.get(thr).toString();
|
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.getClass().getName());
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 }
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: ");
436 FAILED_THREADS.get(thr).toString();
|