1/* 2 * Copyright (c) 2005, 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 * @summary MonitorDeadlock creates threads that are deadlocked on 26 * object monitors. 27 * @author Mandy Chung 28 * @build Barrier 29 */ 30 31import java.lang.management.*; 32import java.util.*; 33 34public class MonitorDeadlock { 35 36 private final int EXPECTED_THREADS = 3; 37 private Barrier go = new Barrier(1); 38 private Barrier barr = new Barrier(EXPECTED_THREADS); 39 40 private Object a = new Object(); 41 private Object b = new Object(); 42 private Object c = new Object(); 43 private Thread[] dThreads = new Thread[EXPECTED_THREADS]; 44 45 public MonitorDeadlock() { 46 dThreads[0] = new DeadlockingThread("MThread-1", a, b); 47 dThreads[1] = new DeadlockingThread("MThread-2", b, c); 48 dThreads[2] = new DeadlockingThread("MThread-3", c, a); 49 50 // make them daemon threads so that the test will exit 51 for (int i = 0; i < EXPECTED_THREADS; i++) { 52 dThreads[i].setDaemon(true); 53 dThreads[i].start(); 54 } 55 } 56 57 void goDeadlock() { 58 // Wait until all threads have started 59 barr.await(); 60 61 // reset for later signals 62 barr.set(EXPECTED_THREADS); 63 64 while (go.getWaiterCount() != EXPECTED_THREADS) { 65 synchronized(this) { 66 try { 67 wait(100); 68 } catch (InterruptedException e) { 69 // ignore 70 } 71 } 72 } 73 74 // sleep a little so that all threads are blocked before notified. 75 try { 76 Thread.sleep(100); 77 } catch (InterruptedException e) { 78 // ignore 79 } 80 go.signal(); 81 82 } 83 84 void waitUntilDeadlock() { 85 barr.await(); 86 87 for (int i=0; i < 100; i++) { 88 // sleep a little while to wait until threads are blocked. 89 try { 90 Thread.sleep(100); 91 } catch (InterruptedException e) { 92 // ignore 93 } 94 boolean retry = false; 95 for (Thread t: dThreads) { 96 if (t.getState() == Thread.State.RUNNABLE) { 97 retry = true; 98 break; 99 } 100 } 101 if (!retry) { 102 break; 103 } 104 } 105 } 106 107 private class DeadlockingThread extends Thread { 108 private final Object lock1; 109 private final Object lock2; 110 111 DeadlockingThread(String name, Object lock1, Object lock2) { 112 super(name); 113 this.lock1 = lock1; 114 this.lock2 = lock2; 115 } 116 public void run() { 117 f(); 118 } 119 private void f() { 120 synchronized (lock1) { 121 barr.signal(); 122 go.await(); 123 g(); 124 } 125 } 126 private void g() { 127 barr.signal(); 128 synchronized (lock2) { 129 throw new RuntimeException("should not reach here."); 130 } 131 } 132 } 133 134 void checkResult(long[] threads) { 135 if (threads.length != EXPECTED_THREADS) { 136 throw new RuntimeException("Expected to have " + 137 EXPECTED_THREADS + " to be in the deadlock list"); 138 } 139 boolean[] found = new boolean[EXPECTED_THREADS]; 140 for (int i = 0; i < threads.length; i++) { 141 for (int j = 0; j < dThreads.length; j++) { 142 if (dThreads[j].getId() == threads[i]) { 143 found[j] = true; 144 } 145 } 146 } 147 boolean ok = true; 148 for (int j = 0; j < found.length; j++) { 149 ok = ok && found[j]; 150 } 151 152 if (!ok) { 153 System.out.print("Returned result is ["); 154 for (int j = 0; j < threads.length; j++) { 155 System.out.print(threads[j] + " "); 156 } 157 System.out.println("]"); 158 159 System.out.print("Expected result is ["); 160 for (int j = 0; j < threads.length; j++) { 161 System.out.print(dThreads[j] + " "); 162 } 163 System.out.println("]"); 164 throw new RuntimeException("Unexpected result returned " + 165 " by findMonitorDeadlockedThreads method."); 166 } 167 } 168} 169