jdk/test/java/lang/management/ThreadMXBean/SynchronizationStatistics.java
changeset 22568 8871c88d0793
parent 19814 77d0468c8874
child 25181 216e0899f503
equal deleted inserted replaced
22567:5816a47fa4dd 22568:8871c88d0793
     1 /*
     1 /*
     2  * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     7  * published by the Free Software Foundation.
    25  * @test
    25  * @test
    26  * @bug     4530538
    26  * @bug     4530538
    27  * @summary Basic unit test of the synchronization statistics support:
    27  * @summary Basic unit test of the synchronization statistics support:
    28  *
    28  *
    29  * @author  Mandy Chung
    29  * @author  Mandy Chung
    30  *
    30  * @author  Jaroslav Bachorik
    31  * @ignore  6309226
    31  *
    32  * @build Semaphore
       
    33  * @run main/othervm SynchronizationStatistics
    32  * @run main/othervm SynchronizationStatistics
    34  */
    33  */
    35 
    34 
    36 import java.lang.management.*;
    35 import java.lang.management.*;
       
    36 import java.util.concurrent.Phaser;
    37 
    37 
    38 public class SynchronizationStatistics {
    38 public class SynchronizationStatistics {
    39     private static ThreadMXBean mbean = ManagementFactory.getThreadMXBean();
    39     private static class LockerThread extends Thread {
    40 
    40         public LockerThread(Runnable r) {
    41     private static boolean blockedTimeCheck =
    41             super(r, "LockerThread");
       
    42         }
       
    43     }
       
    44 
       
    45     private static final ThreadMXBean mbean = ManagementFactory.getThreadMXBean();
       
    46 
       
    47     private static final boolean blockedTimeCheck =
    42         mbean.isThreadContentionMonitoringSupported();
    48         mbean.isThreadContentionMonitoringSupported();
    43     private static boolean trace = false;
    49 
    44 
       
    45     private static Object lockA = new Object();
       
    46     private static Object lockB = new Object();
       
    47     private static Object lockC = new Object();
       
    48     private static Object lockD = new Object();
       
    49     private static Object waiter = new Object();
       
    50     private static volatile boolean testFailed = false;
       
    51 
       
    52     private static Object go = new Object();
       
    53 
       
    54     private static void goSleep(long ms) {
       
    55         try {
       
    56             Thread.sleep(ms);
       
    57         } catch (InterruptedException e) {
       
    58             e.printStackTrace();
       
    59             System.out.println("Unexpected exception.");
       
    60             testFailed = true;
       
    61         }
       
    62     }
       
    63 
    50 
    64     public static void main(String args[]) throws Exception {
    51     public static void main(String args[]) throws Exception {
    65         if (args.length > 0 && args[0].equals("trace")) {
       
    66             trace = true;
       
    67         }
       
    68 
       
    69         if (blockedTimeCheck) {
    52         if (blockedTimeCheck) {
    70             mbean.setThreadContentionMonitoringEnabled(true);
    53             mbean.setThreadContentionMonitoringEnabled(true);
    71         }
    54         }
    72 
    55 
    73         if (!mbean.isThreadContentionMonitoringEnabled()) {
    56         if (!mbean.isThreadContentionMonitoringEnabled()) {
    74             throw new RuntimeException("TEST FAILED: " +
    57             throw new RuntimeException("TEST FAILED: " +
    75                 "Thread Contention Monitoring is not enabled");
    58                 "Thread Contention Monitoring is not enabled");
    76         }
    59         }
    77 
    60 
    78         Examiner examiner = new Examiner("Examiner");
    61         testBlockingOnSimpleMonitor();
    79         BlockedThread blocked = new BlockedThread("BlockedThread");
    62         testBlockingOnNestedMonitor();
    80         examiner.setThread(blocked);
    63         testWaitingOnSimpleMonitor();
    81 
    64         testMultiWaitingOnSimpleMonitor();
    82         // Start the threads and check them in  Blocked and Waiting states
    65         testWaitingOnNestedMonitor();
    83         examiner.start();
       
    84 
       
    85         // wait until the examiner acquires all the locks and waiting
       
    86         // for the BlockedThread to start
       
    87         examiner.waitUntilWaiting();
       
    88 
       
    89         System.out.println("Checking the thread state for the examiner thread " +
       
    90                            "is waiting to begin.");
       
    91 
       
    92         // The Examiner should be waiting to be notified by the BlockedThread
       
    93         checkThreadState(examiner, Thread.State.WAITING);
       
    94 
       
    95         System.out.println("Now starting the blocked thread");
       
    96         blocked.start();
       
    97 
       
    98         try {
       
    99             examiner.join();
       
   100             blocked.join();
       
   101         } catch (InterruptedException e) {
       
   102             e.printStackTrace();
       
   103             System.out.println("Unexpected exception.");
       
   104             testFailed = true;
       
   105         }
       
   106 
       
   107         if (testFailed)
       
   108             throw new RuntimeException("TEST FAILED.");
       
   109 
    66 
   110         System.out.println("Test passed.");
    67         System.out.println("Test passed.");
   111     }
    68     }
   112 
    69 
   113     private static String INDENT = "    ";
    70     private static LockerThread newLockerThread(Runnable r) {
   114     private static void printStack(Thread t, StackTraceElement[] stack) {
    71         LockerThread t = new LockerThread(r);
   115         System.out.println(INDENT +  t +
    72         t.setDaemon(true);
   116                            " stack: (length = " + stack.length + ")");
    73         return t;
   117         if (t != null) {
    74     }
   118             for (int j = 0; j < stack.length; j++) {
    75 
   119                 System.out.println(INDENT + stack[j]);
    76     private static void waitForThreadState(Thread t, Thread.State state) throws InterruptedException {
   120             }
    77         while (!t.isInterrupted() && t.getState() != state) {
   121             System.out.println();
    78             Thread.sleep(3);
   122         }
    79         }
   123     }
    80     }
   124 
    81 
   125     private static void checkThreadState(Thread thread, Thread.State s)
    82     /**
   126         throws Exception {
    83      * Tests that blocking on a single monitor properly increases the
   127 
    84      * blocked count at least by 1. Also asserts that the correct lock name is provided.
   128         ThreadInfo ti = mbean.getThreadInfo(thread.getId());
    85      */
   129         if (ti.getThreadState() != s) {
    86     private static void testBlockingOnSimpleMonitor() throws Exception {
   130             ThreadInfo info = mbean.getThreadInfo(thread.getId(),
    87         System.out.println("testBlockingOnSimpleMonitor");
   131                                                   Integer.MAX_VALUE);
    88         final Object lock1 = new Object();
   132             System.out.println(INDENT + "TEST FAILED:");
    89         final Phaser p = new Phaser(2);
   133             printStack(thread, info.getStackTrace());
    90         LockerThread lt = newLockerThread(new Runnable() {
   134             System.out.println(INDENT + "Thread state: " + info.getThreadState());
    91             @Override
   135 
    92             public void run() {
   136             throw new RuntimeException("TEST FAILED: " +
    93                 p.arriveAndAwaitAdvance(); // phase[1]
   137                 "Thread state for " + thread + " returns " + ti.getThreadState() +
    94                 synchronized(lock1) {
   138                 ".  Expected to be " + s);
    95                     System.out.println("[LockerThread obtained Lock1]");
   139         }
    96                     p.arriveAndAwaitAdvance(); // phase[2]
   140     }
    97                 }
   141 
    98                 p.arriveAndAwaitAdvance(); // phase[3]
   142     private static void checkThreadState(Thread thread,
    99             }
   143                                          Thread.State s1, Thread.State s2)
   100         });
   144         throws Exception {
   101 
   145 
   102         lt.start();
   146         ThreadInfo ti = mbean.getThreadInfo(thread.getId());
   103         long tid = lt.getId();
   147         if (ti.getThreadState() != s1 && ti.getThreadState() != s2) {
   104         ThreadInfo ti = mbean.getThreadInfo(tid);
   148             throw new RuntimeException("TEST FAILED: " +
   105         String lockName = null;
   149                 "Thread state for " + thread + " returns " + ti.getThreadState() +
   106         synchronized(lock1) {
   150                 ".  Expected to be " + s1 + " or " + s2);
   107             p.arriveAndAwaitAdvance(); // phase[1]
   151         }
   108             waitForThreadState(lt, Thread.State.BLOCKED);
   152     }
   109             lockName = mbean.getThreadInfo(tid).getLockName();
   153 
   110         }
   154     static class StatThread extends Thread {
   111 
   155         private long blockingBaseTime = 0;
   112         p.arriveAndAwaitAdvance(); // phase[2]
   156         private long totalWaitTime = 0;
   113         testBlocked(ti, mbean.getThreadInfo(tid), lockName, lock1);
   157         private long totalBlockedEnterTime = 0;
   114         p.arriveAndDeregister(); // phase[3]
   158 
   115 
   159         StatThread(String name) {
   116         lt.join();
   160             super(name);
   117 
   161         }
   118         System.out.println("OK");
   162 
   119     }
   163         void addWaitTime(long ns) {
   120 
   164             totalWaitTime = totalWaitTime + ns;
   121     /**
   165         }
   122      * Tests that blocking on a nested monitor properly increases the
   166         void addBlockedEnterTime(long ns) {
   123      * blocked count at least by 1 - it is not affected by the nesting depth.
   167             totalBlockedEnterTime = totalBlockedEnterTime + ns;
   124      * Also asserts that the correct lock name is provided.
   168         }
   125      */
   169         void setBlockingBaseTime(long time) {
   126     private static void testBlockingOnNestedMonitor() throws Exception {
   170             blockingBaseTime = time;
   127         System.out.println("testBlockingOnNestedMonitor");
   171         }
   128         final Object lock1 = new Object();
   172 
   129         final Object lock2 = new Object();
   173         long totalBlockedTimeMs() {
   130 
   174             return totalBlockedEnterTime / 1000000;
   131         final Phaser p = new Phaser(2);
   175         }
   132         LockerThread lt = newLockerThread(new Runnable() {
   176 
   133             @Override
   177         long totalBlockedTimeMs(long now) {
   134             public void run() {
   178             long t = totalBlockedEnterTime + (now - blockingBaseTime);
   135                 p.arriveAndAwaitAdvance(); // phase[1]
   179             return t / 1000000;
   136                 synchronized(lock1) {
   180         }
   137                     System.out.println("[LockerThread obtained Lock1]");
   181 
   138                     p.arriveAndAwaitAdvance(); // phase[2]
   182         long totalWaitTimeMs() {
   139                     p.arriveAndAwaitAdvance(); // phase[3]
   183             return totalWaitTime / 1000000;
   140                     synchronized(lock2) {
   184         }
   141                         System.out.println("[LockerThread obtained Lock2]");
   185 
   142                         p.arriveAndAwaitAdvance(); // phase[4]
   186         long totalWaitTimeMs(long now) {
   143                     }
   187             long t = totalWaitTime + (now - blockingBaseTime);
   144                     p.arriveAndAwaitAdvance(); // phase[5]
   188             return t / 1000000;
   145                 }
   189         }
   146             }
   190     }
   147         });
   191 
   148 
   192     static class BlockedThread extends StatThread {
   149         lt.start();
   193         private Semaphore handshake = new Semaphore();
   150         long tid = lt.getId();
   194         BlockedThread(String name) {
   151         ThreadInfo ti = mbean.getThreadInfo(tid);
   195             super(name);
   152         ThreadInfo ti1 = null;
   196         }
   153         String lockName = null;
   197         void waitUntilBlocked() {
   154         synchronized(lock1) {
   198             handshake.semaP();
   155             p.arriveAndAwaitAdvance(); // phase[1]
   199 
   156             waitForThreadState(lt, Thread.State.BLOCKED);
   200             // give a chance for the examiner thread to really wait
   157             lockName = mbean.getThreadInfo(tid).getLockName();
   201             goSleep(20);
   158         }
   202         }
   159         p.arriveAndAwaitAdvance(); // phase[2]
   203 
   160 
   204         void waitUntilWaiting() {
   161         ti1 = mbean.getThreadInfo(tid);
   205             waitUntilBlocked();
   162         testBlocked(ti, ti1, lockName, lock1);
   206         }
   163         ti = ti1;
   207 
   164 
   208         boolean hasWaitersForBlocked() {
   165         synchronized(lock2) {
   209             return (handshake.getWaiterCount() > 0);
   166             p.arriveAndAwaitAdvance(); // phase [3]
   210         }
   167             waitForThreadState(lt, Thread.State.BLOCKED);
   211 
   168             lockName = mbean.getThreadInfo(tid).getLockName();
   212         private void notifyWaiter() {
   169         }
   213             // wait until the examiner waits on the semaphore
   170         p.arriveAndAwaitAdvance(); // phase [4]
   214             while (handshake.getWaiterCount() == 0) {
   171         testBlocked(ti, mbean.getThreadInfo(tid), lockName, lock2);
   215                 goSleep(20);
   172         p.arriveAndDeregister();
   216             }
   173 
   217             handshake.semaV();
   174         lt.join();
   218         }
   175 
   219 
   176         System.out.println("OK");
   220         private void waitObj(long ms) {
   177     }
   221             synchronized (waiter) {
   178 
   222                 try {
   179     /**
   223                     // notify examinerabout to wait on a monitor
   180      * Tests that waiting on a single monitor properly increases the waited
   224                     notifyWaiter();
   181      * count by 1 and the waited time by a positive number.
   225 
   182      */
   226                     long base = System.nanoTime();
   183     private static void testWaitingOnSimpleMonitor() throws Exception {
   227                     setBlockingBaseTime(base);
   184         System.out.println("testWaitingOnSimpleMonitor");
   228                     waiter.wait(ms);
   185         final Object lock1 = new Object();
   229                     long now = System.nanoTime();
   186         final Phaser p = new Phaser(2);
   230                     addWaitTime(now - base);
   187         LockerThread lt = newLockerThread(new Runnable() {
   231                 } catch (Exception e) {
   188             @Override
   232                     e.printStackTrace();
   189             public void run() {
   233                     System.out.println("Unexpected exception.");
   190                 p.arriveAndAwaitAdvance(); // phase[1]
   234                     testFailed = true;
   191                 synchronized(lock1) {
   235                 }
   192                     System.out.println("[LockerThread obtained Lock1]");
   236             }
   193                     try {
   237         }
   194                         lock1.wait(300);
   238 
   195                     } catch (InterruptedException ex) {
   239         private void test() {
   196                         // ignore
   240             // notify examiner about to block on lockA
   197                     }
   241             notifyWaiter();
   198                     p.arriveAndAwaitAdvance(); // phase[2]
   242 
   199                 }
   243             long base = System.nanoTime();
   200                 p.arriveAndAwaitAdvance(); // phase[3]
   244             setBlockingBaseTime(base);
   201             }
   245             synchronized (lockA) {
   202         });
   246                 long now = System.nanoTime();
   203 
   247                 addBlockedEnterTime(now - base);
   204         lt.start();
   248 
   205         ThreadInfo ti1 = mbean.getThreadInfo(lt.getId());
   249                 A(); // Expected blocked count = 1
   206         synchronized(lock1) {
   250             }
   207             p.arriveAndAwaitAdvance(); // phase[1]
   251             E();
   208             waitForThreadState(lt, Thread.State.BLOCKED);
   252         }
   209         }
   253         private void A() {
   210         p.arriveAndAwaitAdvance(); // phase[2]
   254             // notify examiner about to block on lockB
   211 
   255             notifyWaiter();
   212         ThreadInfo ti2 = mbean.getThreadInfo(lt.getId());
   256 
   213         p.arriveAndDeregister(); // phase[3]
   257             long base = System.nanoTime();
   214 
   258             setBlockingBaseTime(base);
   215         lt.join();
   259             synchronized (lockB) {
   216 
   260                 long now = System.nanoTime();
   217         testWaited(ti1, ti2, 1);
   261                 addBlockedEnterTime(now - base);
   218         System.out.println("OK");
   262 
   219     }
   263                 B(); // Expected blocked count = 2
   220 
   264             }
   221     /**
   265         }
   222      * Tests that waiting multiple times on the same monitor subsequently
   266         private void B() {
   223      * increases the waited count by the number of subsequent calls and the
   267             // notify examiner about to block on lockC
   224      * waited time by a positive number.
   268             notifyWaiter();
   225      */
   269 
   226     private static void testMultiWaitingOnSimpleMonitor() throws Exception {
   270             long base = System.nanoTime();
   227         System.out.println("testWaitingOnMultipleMonitors");
   271             setBlockingBaseTime(base);
   228         final Object lock1 = new Object();
   272             synchronized (lockC) {
   229 
   273                 long now = System.nanoTime();
   230         final Phaser p = new Phaser(2);
   274                 addBlockedEnterTime(now - base);
   231         LockerThread lt = newLockerThread(new Runnable() {
   275 
   232             @Override
   276                 C();  // Expected blocked count = 3
   233             public void run() {
   277             }
   234                 p.arriveAndAwaitAdvance(); // phase[1]
   278         }
   235                 synchronized(lock1) {
   279         private void C() {
   236                     System.out.println("[LockerThread obtained Lock1]");
   280             // notify examiner about to block on lockD
   237                     for (int i = 0; i < 3; i++) {
   281             notifyWaiter();
   238                         try {
   282 
   239                             lock1.wait(300);
   283             long base = System.nanoTime();
   240                         } catch (InterruptedException ex) {
   284             setBlockingBaseTime(base);
   241                             // ignore
   285             synchronized (lockD) {
   242                         }
   286                 long now = System.nanoTime();
   243                         p.arriveAndAwaitAdvance(); // phase[2-4]
   287                 addBlockedEnterTime(now - base);
   244                     }
   288 
   245                 }
   289                 D();  // Expected blocked count = 4
   246                 p.arriveAndAwaitAdvance(); // phase[5]
   290             }
   247             }
   291         }
   248         });
   292         private void D() {
   249 
   293             goSleep(50);
   250         lt.start();
   294         }
   251         ThreadInfo ti1 = mbean.getThreadInfo(lt.getId());
   295         private void E() {
   252         synchronized(lock1) {
   296             final int WAIT = 1000;
   253             p.arriveAndAwaitAdvance(); //phase[1]
   297             waitObj(WAIT);
   254             waitForThreadState(lt, Thread.State.BLOCKED);
   298             waitObj(WAIT);
   255         }
   299             waitObj(WAIT);
   256         int phase = p.getPhase();
   300         }
   257         while ((p.arriveAndAwaitAdvance() - phase) < 3); // phase[2-4]
   301 
   258 
   302         public void run() {
   259         ThreadInfo ti2 = mbean.getThreadInfo(lt.getId());
   303             test();
   260         p.arriveAndDeregister(); // phase[5]
   304         } // run()
   261 
   305     } // BlockedThread
   262         lt.join();
   306 
   263         testWaited(ti1, ti2, 3);
   307     static int blockedCount = 0;
   264         System.out.println("OK");
   308     static int waitedCount = 0;
   265     }
   309     static class Examiner extends StatThread {
   266 
   310         private BlockedThread blockedThread;
   267     /**
   311         private Semaphore semaphore = new Semaphore();
   268      * Tests that waiting on monitors places in nested synchronized blocks
   312 
   269      * properly increases the waited count by the number of times the "lock.wait()"
   313         Examiner(String name) {
   270      * was invoked and the waited time by a positive number.
   314             super(name);
   271      */
   315         }
   272     private static void testWaitingOnNestedMonitor() throws Exception {
   316 
   273         System.out.println("testWaitingOnNestedMonitor");
   317         public void setThread(BlockedThread thread) {
   274         final Object lock1 = new Object();
   318             blockedThread = thread;
   275         final Object lock2 = new Object();
   319         }
   276         final Object lock3 = new Object();
   320 
   277 
   321         private void blockedTimeRangeCheck(StatThread t,
   278         final Phaser p = new Phaser(2);
   322                                            long blockedTime,
   279         LockerThread lt = newLockerThread(new Runnable() {
   323                                            long nowNano)
   280             @Override
   324             throws Exception {
   281             public void run() {
   325             long expected = t.totalBlockedTimeMs(nowNano);
   282                 p.arriveAndAwaitAdvance(); // phase[1]
   326 
   283                 synchronized(lock1) {
   327             // accept 5% range
   284                     System.out.println("[LockerThread obtained Lock1]");
   328             timeRangeCheck(blockedTime, expected, 5);
   285                     try {
   329         }
   286                         lock1.wait(300);
   330         private void waitedTimeRangeCheck(StatThread t,
   287                     } catch (InterruptedException ex) {
   331                                           long waitedTime,
   288                         // ignore
   332                                           long nowNano)
   289                     }
   333             throws Exception {
   290 
   334             long expected = t.totalWaitTimeMs(nowNano);
   291                     p.arriveAndAwaitAdvance(); // phase[2]
   335 
   292                     synchronized(lock2) {
   336             // accept 5% range
   293                         System.out.println("[LockerThread obtained Lock2]");
   337             timeRangeCheck(waitedTime, expected, 5);
   294                         try {
   338         }
   295                             lock2.wait(300);
   339 
   296                         } catch (InterruptedException ex) {
   340         private void timeRangeCheck(long time, long expected, int percent)
   297                             // ignore
   341             throws Exception {
   298                         }
   342 
   299 
   343             double diff = expected - time;
   300                         p.arriveAndAwaitAdvance(); // phase[3]
   344 
   301                         synchronized(lock3) {
   345             if (trace) {
   302                             System.out.println("[LockerThread obtained Lock3]");
   346                  System.out.println("  Time = " + time +
   303                             try {
   347                     " expected = " + expected +
   304                                 lock3.wait(300);
   348                     ".  Diff = " + diff);
   305                             } catch (InterruptedException ex) {
   349 
   306                                 // ignore
   350             }
       
   351             // throw an exception if blockedTime and expectedTime
       
   352             // differs > percent%
       
   353             if (diff < 0) {
       
   354                 diff = diff * -1;
       
   355             }
       
   356 
       
   357             long range = (expected * percent) / 100;
       
   358             // minimum range = 2 ms
       
   359             if (range < 2) {
       
   360                 range = 2;
       
   361             }
       
   362             if (diff > range) {
       
   363                 throw new RuntimeException("TEST FAILED: " +
       
   364                     "Time returned = " + time +
       
   365                     " expected = " + expected + ".  Diff = " + diff);
       
   366             }
       
   367         }
       
   368         private void checkInfo(StatThread t, Thread.State s, Object lock,
       
   369                                String lockName, int bcount, int wcount)
       
   370             throws Exception {
       
   371 
       
   372             String action = "ERROR";
       
   373             if (s == Thread.State.WAITING || s == Thread.State.TIMED_WAITING) {
       
   374                 action = "wait on ";
       
   375             } else if (s == Thread.State.BLOCKED) {
       
   376                 action = "block on ";
       
   377             }
       
   378             System.out.println(t + " expected to " + action + lockName +
       
   379                 " with blocked count = " + bcount +
       
   380                 " and waited count = " + wcount);
       
   381 
       
   382             long now = System.nanoTime();
       
   383             ThreadInfo info = mbean.getThreadInfo(t.getId());
       
   384             if (info.getThreadState() != s) {
       
   385                 printStack(t, info.getStackTrace());
       
   386                 throw new RuntimeException("TEST FAILED: " +
       
   387                     "Thread state returned is " + info.getThreadState() +
       
   388                     ". Expected to be " + s);
       
   389             }
       
   390 
       
   391             if (info.getLockName() == null ||
       
   392                 !info.getLockName().equals(lock.toString())) {
       
   393                 throw new RuntimeException("TEST FAILED: " +
       
   394                     "getLockName() returned " + info.getLockName() +
       
   395                     ". Expected to be " + lockName + " - "  + lock.toString());
       
   396             }
       
   397 
       
   398             if (info.getBlockedCount() != bcount) {
       
   399                 throw new RuntimeException("TEST FAILED: " +
       
   400                     "Blocked Count returned is " + info.getBlockedCount() +
       
   401                     ". Expected to be " + bcount);
       
   402             }
       
   403             if (info.getWaitedCount() != wcount) {
       
   404                 throw new RuntimeException("TEST FAILED: " +
       
   405                     "Waited Count returned is " + info.getWaitedCount() +
       
   406                     ". Expected to be " + wcount);
       
   407             }
       
   408 
       
   409             String lockObj = info.getLockName();
       
   410             if (lockObj == null || !lockObj.equals(lock.toString())) {
       
   411                 throw new RuntimeException("TEST FAILED: " +
       
   412                     "Object blocked on is " + lockObj  +
       
   413                     ". Expected to be " + lock.toString());
       
   414             }
       
   415 
       
   416             if (!blockedTimeCheck) {
       
   417                 return;
       
   418             }
       
   419             long blockedTime = info.getBlockedTime();
       
   420             if (blockedTime < 0) {
       
   421                 throw new RuntimeException("TEST FAILED: " +
       
   422                     "Blocked time returned is negative = " + blockedTime);
       
   423             }
       
   424 
       
   425             if (s == Thread.State.BLOCKED) {
       
   426                 blockedTimeRangeCheck(t, blockedTime, now);
       
   427             } else {
       
   428                 timeRangeCheck(blockedTime, t.totalBlockedTimeMs(), 5);
       
   429             }
       
   430 
       
   431             long waitedTime = info.getWaitedTime();
       
   432             if (waitedTime < 0) {
       
   433                 throw new RuntimeException("TEST FAILED: " +
       
   434                     "Waited time returned is negative = " + waitedTime);
       
   435             }
       
   436             if (s == Thread.State.WAITING || s == Thread.State.TIMED_WAITING) {
       
   437                 waitedTimeRangeCheck(t, waitedTime, now);
       
   438             } else {
       
   439                 timeRangeCheck(waitedTime, t.totalWaitTimeMs(), 5);
       
   440             }
       
   441 
       
   442         }
       
   443 
       
   444         private void examine() {
       
   445             try {
       
   446                 synchronized (lockD) {
       
   447                     synchronized (lockC) {
       
   448                         synchronized (lockB) {
       
   449                             synchronized (lockA) {
       
   450                                 // notify main thread to continue
       
   451                                 semaphore.semaV();
       
   452 
       
   453                                 // wait until BlockedThread has started
       
   454                                 blockedThread.waitUntilBlocked();
       
   455 
       
   456                                 blockedCount++;
       
   457                                 checkInfo(blockedThread, Thread.State.BLOCKED,
       
   458                                           lockA, "lockA",
       
   459                                           blockedCount, waitedCount);
       
   460                             }
   307                             }
   461 
   308                             p.arriveAndAwaitAdvance(); // phase[4]
   462                            // wait until BlockedThread to block on lockB
       
   463                             blockedThread.waitUntilBlocked();
       
   464 
       
   465                             blockedCount++;
       
   466                             checkInfo(blockedThread, Thread.State.BLOCKED,
       
   467                                       lockB, "lockB",
       
   468                                       blockedCount, waitedCount);
       
   469                         }
   309                         }
   470 
   310                     }
   471                         // wait until BlockedThread to block on lockC
   311                 }
   472                         blockedThread.waitUntilBlocked();
   312                 p.arriveAndAwaitAdvance(); // phase[5]
   473 
   313             }
   474                         blockedCount++;
   314         });
   475                         checkInfo(blockedThread, Thread.State.BLOCKED,
   315 
   476                                   lockC, "lockC",
   316         lt.start();
   477                                   blockedCount, waitedCount);
   317         ThreadInfo ti1 = mbean.getThreadInfo(lt.getId());
   478                     }
   318         synchronized(lock1) {
   479                     // wait until BlockedThread to block on lockD
   319             p.arriveAndAwaitAdvance(); // phase[1]
   480                     blockedThread.waitUntilBlocked();
   320             waitForThreadState(lt, Thread.State.BLOCKED);
   481                     blockedCount++;
   321         }
   482 
   322 
   483                     checkInfo(blockedThread, Thread.State.BLOCKED,
   323         synchronized(lock2) {
   484                               lockD, "lockD",
   324             p.arriveAndAwaitAdvance(); // phase[2]
   485                               blockedCount, waitedCount);
   325             waitForThreadState(lt, Thread.State.BLOCKED);
   486                 }
   326         }
   487 
   327 
   488                 // wait until BlockedThread about to call E()
   328         synchronized(lock3) {
   489                 // BlockedThread will wait on waiter for 3 times
   329             p.arriveAndAwaitAdvance(); // phase[3]
   490                 blockedThread.waitUntilWaiting();
   330             waitForThreadState(lt, Thread.State.BLOCKED);
   491 
   331         }
   492                 waitedCount++;
   332 
   493                 checkInfo(blockedThread, Thread.State.TIMED_WAITING,
   333         p.arriveAndAwaitAdvance(); // phase[4]
   494                           waiter, "waiter", blockedCount, waitedCount);
   334         ThreadInfo ti2 = mbean.getThreadInfo(lt.getId());
   495 
   335         p.arriveAndDeregister(); // phase[5]
   496                 blockedThread.waitUntilWaiting();
   336 
   497 
   337         lt.join();
   498                 waitedCount++;
   338         testWaited(ti1, ti2, 3);
   499                 checkInfo(blockedThread, Thread.State.TIMED_WAITING,
   339         System.out.println("OK");
   500                           waiter, "waiter", blockedCount, waitedCount);
   340     }
   501 
   341 
   502                 blockedThread.waitUntilWaiting();
   342     private static void testWaited(ThreadInfo ti1, ThreadInfo ti2, int waited) throws Error {
   503 
   343         long waitCntDiff = ti2.getWaitedCount() - ti1.getWaitedCount();
   504                 waitedCount++;
   344         long waitTimeDiff = ti2.getWaitedTime() - ti1.getWaitedTime();
   505                 checkInfo(blockedThread, Thread.State.TIMED_WAITING,
   345         if (waitCntDiff < waited) {
   506                           waiter, "waiter", blockedCount, waitedCount);
   346             throw new Error("Unexpected diff in waited count. Expecting at least "
   507 
   347                             + waited + " , got " + waitCntDiff);
   508             } catch (Exception e) {
   348         }
   509                 e.printStackTrace();
   349         if (waitTimeDiff <= 0) {
   510                 System.out.println("Unexpected exception.");
   350             throw new Error("Unexpected diff in waited time. Expecting increasing " +
   511                 testFailed = true;
   351                             "value, got " + waitTimeDiff + "ms");
   512             }
   352         }
   513         }
   353     }
   514 
   354 
   515         public void run() {
   355     private static void testBlocked(ThreadInfo ti1, ThreadInfo ti2,
   516             examine();
   356                                     String lockName, final Object lock)
   517         } // run()
   357     throws Error {
   518 
   358         long blkCntDiff = ti2.getBlockedCount() - ti1.getBlockedCount();
   519         public void waitUntilWaiting() {
   359         long blkTimeDiff = ti2.getBlockedTime() - ti1.getBlockedTime();
   520             semaphore.semaP();
   360         if (blkCntDiff < 1) {
   521 
   361             throw new Error("Unexpected diff in blocked count. Expecting at least 1, " +
   522             // wait until the examiner is waiting for
   362                             "got " + blkCntDiff);
   523             while (!blockedThread.hasWaitersForBlocked()) {
   363         }
   524                 goSleep(50);
   364         if (blkTimeDiff < 0) {
   525             }
   365             throw new Error("Unexpected diff in blocked time. Expecting a positive " +
   526             // give a chance for the examiner thread to really wait
   366                             "number, got " + blkTimeDiff);
   527             goSleep(20);
   367         }
   528 
   368         if (!lockName.equals(lock.toString())) {
   529         }
   369             throw new Error("Unexpected blocked monitor name. Expecting " +
   530     } // Examiner
   370                     lock.toString() + ", got " +
       
   371                     lockName);
       
   372         }
       
   373     }
   531 }
   374 }