1 /* 2 * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 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 7 * published by the Free Software Foundation. 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 * @bug 4530538 27 * @summary Basic unit test of ThreadInfo.getBlockedCount() 28 * @author Alexei Guibadoulline and Mandy Chung 29 * @author Jaroslav Bachorik 30 * @run main ThreadBlockedCount 31 */ 32 33 import java.lang.management.*; 34 import java.util.concurrent.Phaser; 35 36 public class ThreadBlockedCount { 37 final static long EXPECTED_BLOCKED_COUNT = 3; 38 final static int DEPTH = 10; 39 private static final ThreadMXBean mbean 40 = ManagementFactory.getThreadMXBean(); 41 42 private static final Object a = new Object(); 43 private static final Object b = new Object(); 44 private static final Object c = new Object(); 45 46 private static final Object blockedObj1 = new Object(); 47 private static final Object blockedObj2 = new Object(); 48 private static final Object blockedObj3 = new Object(); 49 private static volatile boolean testOk = true; 50 private static BlockingThread blocking; 51 private static BlockedThread blocked; 52 53 public static void main(String args[]) throws Exception { 54 // real run 55 runTest(); 56 if (!testOk) { 57 throw new RuntimeException("TEST FAILED."); 58 } 59 System.out.println("Test passed."); 60 } 61 62 private static void runTest() throws Exception { 63 final Phaser p = new Phaser(2); 64 65 blocking = new BlockingThread(p); 66 blocking.start(); 67 68 blocked = new BlockedThread(p); 69 blocked.start(); 70 71 try { 72 blocking.join(); 73 74 testOk = checkBlocked(); 75 p.arriveAndAwaitAdvance(); // #5 76 77 } catch (InterruptedException e) { 78 System.err.println("Unexpected exception."); 79 e.printStackTrace(System.err); 80 throw e; 81 } 82 } 83 84 85 static class BlockedThread extends Thread { 86 private final Phaser p; 87 88 BlockedThread(Phaser p) { 89 super("BlockedThread"); 90 this.p = p; 91 } 92 93 public void run() { 94 int accumulator = 0; 95 p.arriveAndAwaitAdvance(); // #1 96 97 // Enter lock a without blocking 98 synchronized (a) { 99 p.arriveAndAwaitAdvance(); // #2 100 101 // Block to enter blockedObj1 102 // blockedObj1 should be owned by BlockingThread 103 synchronized (blockedObj1) { 104 accumulator++; // filler 105 } 106 } 107 108 // Enter lock a without blocking 109 synchronized (b) { 110 // wait until BlockingThread holds blockedObj2 111 p.arriveAndAwaitAdvance(); // #3 112 113 // Block to enter blockedObj2 114 // blockedObj2 should be owned by BlockingThread 115 synchronized (blockedObj2) { 116 accumulator++; // filler 117 } 118 } 119 120 // Enter lock a without blocking 121 synchronized (c) { 122 // wait until BlockingThread holds blockedObj3 123 p.arriveAndAwaitAdvance(); // #4 124 125 // Block to enter blockedObj3 126 // blockedObj3 should be owned by BlockingThread 127 synchronized (blockedObj3) { 128 accumulator++; // filler 129 } 130 } 131 132 // wait for the main thread to check the blocked count 133 System.out.println("Acquired " + accumulator + " monitors"); 134 p.arriveAndAwaitAdvance(); // #5 135 // ... and we can leave now 136 } // run() 137 } // BlockedThread 138 139 static class BlockingThread extends Thread { 140 private final Phaser p; 141 142 BlockingThread(Phaser p) { 143 super("BlockingThread"); 144 this.p = p; 145 } 146 147 private void waitForBlocked() { 148 // wait for BlockedThread. 149 p.arriveAndAwaitAdvance(); 150 151 boolean threadBlocked = false; 152 while (!threadBlocked) { 153 // give a chance for BlockedThread to really block 154 try { 155 Thread.sleep(50); 156 } catch (InterruptedException e) { 157 System.err.println("Unexpected exception."); 158 e.printStackTrace(System.err); 159 testOk = false; 160 break; 161 } 162 ThreadInfo info = mbean.getThreadInfo(blocked.getId()); 163 threadBlocked = (info.getThreadState() == Thread.State.BLOCKED); 164 } 165 } 166 167 public void run() { 168 p.arriveAndAwaitAdvance(); // #1 169 170 synchronized (blockedObj1) { 171 System.out.println("BlockingThread attempts to notify a"); 172 waitForBlocked(); // #2 173 } 174 175 // block until BlockedThread is ready 176 synchronized (blockedObj2) { 177 System.out.println("BlockingThread attempts to notify b"); 178 waitForBlocked(); // #3 179 } 180 181 // block until BlockedThread is ready 182 synchronized (blockedObj3) { 183 System.out.println("BlockingThread attempts to notify c"); 184 waitForBlocked(); // #4 185 } 186 187 } // run() 188 } // BlockingThread 189 190 private static long getBlockedCount() { 191 long count; 192 // Check the mbean now 193 ThreadInfo ti = mbean.getThreadInfo(blocked.getId()); 194 count = ti.getBlockedCount(); 195 return count; 196 } 197 198 private static boolean checkBlocked() { 199 // wait for the thread stats to be updated for 10 seconds 200 long count = -1; 201 for (int i = 0; i < 100; i++) { 202 count = getBlockedCount(); 203 if (count >= EXPECTED_BLOCKED_COUNT) { 204 return true; 205 } 206 try { 207 Thread.sleep(100); 208 } catch (InterruptedException e) { 209 System.err.println("Unexpected exception."); 210 e.printStackTrace(System.err); 211 return false; 212 } 213 } 214 System.err.println("TEST FAILED: Blocked thread has " + count + 215 " blocked counts. Expected at least " + 216 EXPECTED_BLOCKED_COUNT); 217 return false; 218 } 219 }