< prev index next >

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

Print this page
@@ -1,7 +1,7 @@
  /*
-  * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+  * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.

@@ -24,10 +24,11 @@
  /*
   * @test
   * @library /test/lib
   *
   * @requires !vm.graal.enabled
+  * @enablePreview
   *
   * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -Xint                   -DTHROW=false -Xcheck:jni ClassInitBarrier
   * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -Xint                   -DTHROW=true  -Xcheck:jni ClassInitBarrier
   *
   * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:TieredStopAtLevel=1 -DTHROW=false -Xcheck:jni ClassInitBarrier

@@ -65,11 +66,20 @@
  
      static native boolean init();
  
      static final boolean THROW = Boolean.getBoolean("THROW");
  
+     static value class MyValue {
+         int x = 42;
+ 
+         void verify() {
+             Asserts.assertEquals(x, 42);
+         }
+     }
+ 
      static class Test {
+ 
          static class A {
              static {
                  if (!init(B.class)) {
                      throw new Error("init failed");
                  }

@@ -83,13 +93,13 @@
                  maybeThrow();    // fail initialization if needed
  
                  changePhase(Phase.FINISHED);
              }
  
-             static              void staticM(Runnable action) { action.run(); }
-             static synchronized void staticS(Runnable action) { action.run(); }
-             static native       void staticN(Runnable action);
+             static              void staticM(Runnable action, MyValue val) { action.run(); val.verify(); }
+             static synchronized void staticS(Runnable action, MyValue val) { action.run(); val.verify(); }
+             static native       void staticN(Runnable action, MyValue val);
  
              static int staticF;
  
              int f;
              void m() {}

@@ -97,35 +107,35 @@
              static native boolean init(Class<B> cls);
          }
  
          static class B extends A {}
  
-         static void testInvokeStatic(Runnable action)       { A.staticM(action); }
-         static void testInvokeStaticSync(Runnable action)   { A.staticS(action); }
-         static void testInvokeStaticNative(Runnable action) { A.staticN(action); }
+         static void testInvokeStatic(Runnable action, MyValue val)       { A.staticM(action, val); }
+         static void testInvokeStaticSync(Runnable action, MyValue val)   { A.staticS(action, val); }
+         static void testInvokeStaticNative(Runnable action, MyValue val) { A.staticN(action, val); }
  
-         static int  testGetStatic(Runnable action)    { int v = A.staticF; action.run(); return v;   }
-         static void testPutStatic(Runnable action)    { A.staticF = 1;     action.run(); }
-         static A    testNewInstanceA(Runnable action) { A obj = new A();   action.run(); return obj; }
-         static B    testNewInstanceB(Runnable action) { B obj = new B();   action.run(); return obj; }
+         static int  testGetStatic(Runnable action, MyValue val)    { int v = A.staticF; action.run(); val.verify(); return v;   }
+         static void testPutStatic(Runnable action, MyValue val)    { A.staticF = 1;     action.run(); val.verify(); }
+         static A    testNewInstanceA(Runnable action, MyValue val) { A obj = new A();   action.run(); val.verify(); return obj; }
+         static B    testNewInstanceB(Runnable action, MyValue val) { B obj = new B();   action.run(); val.verify(); return obj; }
  
-         static int  testGetField(A recv, Runnable action)      { int v = recv.f; action.run(); return v; }
-         static void testPutField(A recv, Runnable action)      { recv.f = 1;     action.run(); }
-         static void testInvokeVirtual(A recv, Runnable action) { recv.m();       action.run(); }
+         static int  testGetField(A recv, Runnable action, MyValue val)      { int v = recv.f; action.run(); val.verify(); return v; }
+         static void testPutField(A recv, Runnable action, MyValue val)      { recv.f = 1;     action.run(); val.verify(); }
+         static void testInvokeVirtual(A recv, Runnable action, MyValue val) { recv.m();       action.run(); val.verify(); }
  
-         static native void testInvokeStaticJNI(Runnable action);
-         static native void testInvokeStaticSyncJNI(Runnable action);
-         static native void testInvokeStaticNativeJNI(Runnable action);
+         static native void testInvokeStaticJNI(Runnable action, MyValue val);
+         static native void testInvokeStaticSyncJNI(Runnable action, MyValue val);
+         static native void testInvokeStaticNativeJNI(Runnable action, MyValue val);
  
-         static native int  testGetStaticJNI(Runnable action);
-         static native void testPutStaticJNI(Runnable action);
-         static native A    testNewInstanceAJNI(Runnable action);
-         static native B    testNewInstanceBJNI(Runnable action);
+         static native int  testGetStaticJNI(Runnable action, MyValue val);
+         static native void testPutStaticJNI(Runnable action, MyValue val);
+         static native A    testNewInstanceAJNI(Runnable action, MyValue val);
+         static native B    testNewInstanceBJNI(Runnable action, MyValue val);
  
-         static native int  testGetFieldJNI(A recv, Runnable action);
-         static native void testPutFieldJNI(A recv, Runnable action);
-         static native void testInvokeVirtualJNI(A recv, Runnable action);
+         static native int  testGetFieldJNI(A recv, Runnable action, MyValue val);
+         static native void testPutFieldJNI(A recv, Runnable action, MyValue val);
+         static native void testInvokeVirtualJNI(A recv, Runnable action, MyValue val);
  
          static void runTests() {
              checkBlockingAction(Test::testInvokeStatic);       // invokestatic
              checkBlockingAction(Test::testInvokeStaticSync);   // invokestatic
              checkBlockingAction(Test::testInvokeStaticNative); // invokestatic

@@ -138,11 +148,11 @@
              checkNonBlockingAction(Test::testInvokeStaticNativeJNI); // invokestatic
              checkNonBlockingAction(Test::testGetStaticJNI);          // getstatic
              checkNonBlockingAction(Test::testPutStaticJNI);          // putstatic
              checkBlockingAction(Test::testNewInstanceAJNI);          // new
  
-             A recv = testNewInstanceB(NON_BLOCKING.get());  // trigger B initialization
+             A recv = testNewInstanceB(NON_BLOCKING.get(), new MyValue());  // trigger B initialization
              checkNonBlockingAction(Test::testNewInstanceB); // new: NO BLOCKING: same thread: A being initialized, B fully initialized
  
              checkNonBlockingAction(recv, Test::testGetField);      // getfield
              checkNonBlockingAction(recv, Test::testPutField);      // putfield
              checkNonBlockingAction(recv, Test::testInvokeVirtual); // invokevirtual

@@ -152,22 +162,23 @@
              checkNonBlockingAction(recv, Test::testPutFieldJNI);      // putfield
              checkNonBlockingAction(recv, Test::testInvokeVirtualJNI); // invokevirtual
          }
  
          static void warmup() {
+             MyValue val = new MyValue();
              for (int i = 0; i < 20_000; i++) {
-                 testInvokeStatic(      NON_BLOCKING_WARMUP);
-                 testInvokeStaticNative(NON_BLOCKING_WARMUP);
-                 testInvokeStaticSync(  NON_BLOCKING_WARMUP);
-                 testGetStatic(         NON_BLOCKING_WARMUP);
-                 testPutStatic(         NON_BLOCKING_WARMUP);
-                 testNewInstanceA(      NON_BLOCKING_WARMUP);
-                 testNewInstanceB(      NON_BLOCKING_WARMUP);
- 
-                 testGetField(new B(),      NON_BLOCKING_WARMUP);
-                 testPutField(new B(),      NON_BLOCKING_WARMUP);
-                 testInvokeVirtual(new B(), NON_BLOCKING_WARMUP);
+                 testInvokeStatic(      NON_BLOCKING_WARMUP, val);
+                 testInvokeStaticNative(NON_BLOCKING_WARMUP, val);
+                 testInvokeStaticSync(  NON_BLOCKING_WARMUP, val);
+                 testGetStatic(         NON_BLOCKING_WARMUP, val);
+                 testPutStatic(         NON_BLOCKING_WARMUP, val);
+                 testNewInstanceA(      NON_BLOCKING_WARMUP, val);
+                 testNewInstanceB(      NON_BLOCKING_WARMUP, val);
+ 
+                 testGetField(new B(),      NON_BLOCKING_WARMUP, val);
+                 testPutField(new B(),      NON_BLOCKING_WARMUP, val);
+                 testInvokeVirtual(new B(), NON_BLOCKING_WARMUP, val);
              }
          }
  
          static void run() {
              execute(ExceptionInInitializerError.class, () -> triggerInitialization(A.class));

@@ -263,15 +274,15 @@
  
          dumpInfo();
      }
  
      interface TestCase0 {
-         void run(Runnable runnable);
+         void run(Runnable runnable, MyValue val);
      }
  
      interface TestCase1<T> {
-         void run(T arg, Runnable runnable);
+         void run(T arg, Runnable runnable, MyValue val);
      }
  
      enum Phase { BEFORE_INIT, IN_PROGRESS, FINISHED, INIT_FAILURE }
  
      static volatile Phase phase = Phase.BEFORE_INIT;

@@ -337,47 +348,48 @@
      static final AtomicInteger BLOCKING_COUNTER = new AtomicInteger(0);
      static final AtomicInteger BLOCKING_ACTIONS = new AtomicInteger(0);
      static final Factory<Runnable> BLOCKING     = () -> disposableAction(Phase.FINISHED, BLOCKING_COUNTER, BLOCKING_ACTIONS);
  
      static void checkBlockingAction(TestCase0 r) {
+         MyValue val = new MyValue();
          switch (phase) {
              case IN_PROGRESS: {
                  // Barrier during class initalization.
-                 r.run(NON_BLOCKING.get());             // initializing thread
+                 r.run(NON_BLOCKING.get(), val);             // initializing thread
                  checkBlocked(ON_BLOCK, ON_FAILURE, r); // different thread
                  break;
              }
              case FINISHED: {
                  // No barrier after class initalization is over.
-                 r.run(NON_BLOCKING.get()); // initializing thread
+                 r.run(NON_BLOCKING.get(), val); // initializing thread
                  checkNotBlocked(r);        // different thread
                  break;
              }
              case INIT_FAILURE: {
                  // Exception is thrown after class initialization failed.
-                 TestCase0 test = action -> execute(NoClassDefFoundError.class, () -> r.run(action));
+                 TestCase0 test = (action, valarg) -> execute(NoClassDefFoundError.class, () -> r.run(action, valarg));
  
-                 test.run(NON_BLOCKING.get()); // initializing thread
+                 test.run(NON_BLOCKING.get(), val); // initializing thread
                  checkNotBlocked(test);        // different thread
                  break;
              }
              default: throw new Error("wrong phase: " + phase);
          }
      }
  
      static void checkNonBlockingAction(TestCase0 r) {
-         r.run(NON_BLOCKING.get()); // initializing thread
+         r.run(NON_BLOCKING.get(), new MyValue()); // initializing thread
          checkNotBlocked(r);        // different thread
      }
  
      static <T> void checkNonBlockingAction(T recv, TestCase1<T> r) {
-         r.run(recv, NON_BLOCKING.get());                  // initializing thread
-         checkNotBlocked((action) -> r.run(recv, action)); // different thread
+         r.run(recv, NON_BLOCKING.get(), new MyValue());                  // initializing thread
+         checkNotBlocked((action, val) -> r.run(recv, action, val)); // different thread
      }
  
      static void checkFailingAction(TestCase0 r) {
-         r.run(NON_BLOCKING.get()); // initializing thread
+         r.run(NON_BLOCKING.get(), new MyValue()); // initializing thread
          checkNotBlocked(r);        // different thread
      }
  
      static void triggerInitialization(Class<?> cls) {
          try {

@@ -391,11 +403,11 @@
      }
  
      static void checkBlocked(Consumer<Thread> onBlockHandler, Thread.UncaughtExceptionHandler onException, TestCase0 r) {
          Thread thr = new Thread(() -> {
              try {
-                 r.run(BLOCKING.get());
+                 r.run(BLOCKING.get(), new MyValue());
                  System.out.println("Thread " + Thread.currentThread() + ": Finished successfully");
              } catch(Throwable e) {
                  System.out.println("Thread " + Thread.currentThread() + ": Exception thrown: " + e);
                  if (!THROW) {
                      e.printStackTrace();

@@ -419,11 +431,11 @@
              throw new Error(e);
          }
      }
  
      static void checkNotBlocked(TestCase0 r) {
-         final Thread thr = new Thread(() -> r.run(NON_BLOCKING.get()));
+         final Thread thr = new Thread(() -> r.run(NON_BLOCKING.get(), new MyValue()));
          final Throwable[] ex = new Throwable[1];
          thr.setUncaughtExceptionHandler((t, e) -> {
              if (thr != t) {
                  ex[0] = new Error("wrong thread: " + thr + " vs " + t);
              } else {
< prev index next >