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