blob: 11fa9d9023a810950cf16a6fbfebff37229564ae [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 */
23
24/*
25 * @bug 5086470 6358247
26 * @summary LockingThread is used by LockedMonitors test.
27 * It will create threads that have:
28 * - a stack frame acquires no monitor
29 * - a stack frame acquires one or more monitors
30 * - a stack frame blocks on Object.wait
31 * and the monitor waiting is not locked.
32 * @author Mandy Chung
33 *
34 * @build Barrier
35 * @build ThreadDump
36 */
37
38import java.lang.management.*;
39import java.util.*;
40
41public class LockingThread extends Thread {
42 static Lock lock1 = new Lock("lock1");
43 static Lock lock2 = new Lock("lock2");
44 static Lock lock3 = new Lock("lock3");
45 static Lock lock4 = new Lock("lock4");
46 static Lock lock5 = new Lock("lock5");
47 static Lock lock6 = new Lock("lock6");
48 static Lock lock7 = new Lock("lock7");
49 static Lock lock8 = new Lock("lock8");
50
51 static LockingThread t1 = new Thread1();
52 static LockingThread t2 = new Thread2();
53 static Barrier barr = new Barrier(2);
54 static int count = 2;
55 static void startLockingThreads() {
56 t1.setDaemon(true);
57 t2.setDaemon(true);
58 t1.start();
59 t2.start();
60
61 // wait until t1 waits
62 while (count != 0) {
63 try {
64 Thread.sleep(100);
65 } catch (InterruptedException e) {
66 throw new RuntimeException(e);
67 }
68 }
69 }
70 static long[] getThreadIds() {
71 return new long[] {t1.getId(), t2.getId()};
72 }
73
74 static void checkLockedMonitors(ThreadInfo[] tinfos)
75 throws Exception {
76
77 int matches = 0;
78 for (ThreadInfo ti : tinfos) {
79 if (ti.getThreadId() == t1.getId()) {
80 t1.checkLockedMonitors(ti);
81 matches++;
82 }
83 if (ti.getThreadId() == t2.getId()) {
84 t2.checkLockedMonitors(ti);
85 matches++;
86 }
87 }
88 if (matches != 2) {
89 throw new RuntimeException("MonitorInfo missing");
90 }
91 }
92
93 static class Lock {
94 String name;
95 Lock(String name) {
96 this.name = name;
97 }
98 public String toString() {
99 return name;
100 }
101 }
102
103 final String threadName;
104 Lock waitingLock;
105 int numOwnedMonitors;
106 Map<String, Lock[]> ownedMonitors;
107 public LockingThread(String name) {
108 this.threadName = name;
109 }
110
111 protected void setExpectedResult(Lock waitingLock,
112 int numOwnedMonitors,
113 Map<String, Lock[]> ownedMonitors) {
114 this.waitingLock = waitingLock;
115 this.numOwnedMonitors = numOwnedMonitors;
116 this.ownedMonitors = ownedMonitors;
117 }
118
119 void checkLockedMonitors(ThreadInfo info)
120 throws Exception {
121 checkThreadInfo(info);
122
123 MonitorInfo[] monitors = info.getLockedMonitors();
124 if (monitors.length != numOwnedMonitors) {
125 ThreadDump.threadDump();
126 throw new RuntimeException("Number of locked monitors = " +
127 monitors.length +
128 " not matched. Expected: " + numOwnedMonitors);
129 }
130 // check if each monitor returned in the list is the expected
131 // one
132 for (MonitorInfo m : monitors) {
133 StackTraceElement ste = m.getLockedStackFrame();
134 int depth = m.getLockedStackDepth();
135 checkStackFrame(info, ste, depth);
136 checkMonitor(m, ste.getMethodName());
137 }
138 // check if each expected monitor is included in the returned
139 // list
140 for (Map.Entry<String, Lock[]> e : ownedMonitors.entrySet()) {
141 for (Lock l : e.getValue()) {
142 checkMonitor(e.getKey(), l, monitors);
143 }
144 }
145
146 if (info.getLockedSynchronizers().length != 0) {
147 ThreadDump.threadDump();
148 throw new RuntimeException("Number of locked synchronizers = " +
149 info.getLockedSynchronizers().length +
150 " not matched. Expected: 0.");
151 }
152 }
153
154 void checkThreadInfo(ThreadInfo info) throws Exception {
155 if (!getName().equals(info.getThreadName())) {
156 throw new RuntimeException("Name: " + info.getThreadName() +
157 " not matched. Expected: " + getName());
158 }
159 LockInfo l = info.getLockInfo();
160 if ((waitingLock == null && l != null) ||
161 (waitingLock != null && l == null)) {
162 throw new RuntimeException("LockInfo: " + l +
163 " not matched. Expected: " + waitingLock);
164 }
165
166 String waitingLockName = waitingLock.getClass().getName();
167 int hcode = System.identityHashCode(waitingLock);
168 if (!waitingLockName.equals(l.getClassName())) {
169 throw new RuntimeException("LockInfo : " + l +
170 " class name not matched. Expected: " + waitingLockName);
171 }
172 if (hcode != l.getIdentityHashCode()) {
173 throw new RuntimeException("LockInfo: " + l +
174 " IdentityHashCode not matched. Expected: " + hcode);
175 }
176
177 String lockName = info.getLockName();
178 String[] s = lockName.split("@");
179 if (!waitingLockName.equals(s[0])) {
180 throw new RuntimeException("LockName: " + lockName +
181 " class name not matched. Expected: " + waitingLockName);
182 }
183 int i = Integer.parseInt(s[1], 16);
184 if (hcode != i) {
185 throw new RuntimeException("LockName: " + lockName +
186 " IdentityHashCode not matched. Expected: " + hcode);
187 }
188 }
189
190 void checkStackFrame(ThreadInfo info, StackTraceElement ste, int depth) {
191 StackTraceElement[] stacktrace = info.getStackTrace();
192 if (!ste.equals(stacktrace[depth])) {
193 System.out.println("LockedStackFrame:- " + ste);
194 System.out.println("StackTrace at " + depth + " :-" +
195 stacktrace[depth]);
196 throw new RuntimeException("LockedStackFrame does not match " +
197 "stack frame in ThreadInfo.getStackTrace");
198 }
199 }
200 void checkMonitor(MonitorInfo m, String methodName) {
201 for (Map.Entry<String, Lock[]> e : ownedMonitors.entrySet()) {
202 if (methodName.equals(e.getKey())) {
203 for (Lock l : e.getValue()) {
204 String className = l.getClass().getName();
205 int hcode = System.identityHashCode(l);
206 if (className.equals(m.getClassName()) &&
207 hcode == m.getIdentityHashCode()) {
208 // monitor matched the expected
209 return;
210 }
211 }
212 }
213 }
214 throw new RuntimeException("Monitor not expected" + m);
215 }
216 void checkMonitor(String methodName, Lock l, MonitorInfo[] monitors) {
217 String className = l.getClass().getName();
218 int hcode = System.identityHashCode(l);
219 for (MonitorInfo m : monitors) {
220 if (className.equals(m.getClassName()) &&
221 hcode == m.getIdentityHashCode() &&
222 methodName.equals(m.getLockedStackFrame().getMethodName())) {
223 return;
224 }
225 }
226 throw new RuntimeException("Monitor not found in the returned list" +
227 " Method: " + methodName + " Lock: " + l);
228
229 }
230
231 static class Thread1 extends LockingThread {
232 public Thread1() {
233 super("t1");
234 initExpectedResult();
235 }
236 public void run() {
237 A();
238 }
239 void A() {
240 synchronized(lock1) {
241 synchronized(lock2) {
242 synchronized(lock3) {
243 B();
244 }
245 }
246 }
247 }
248 void B() {
249 synchronized(lock4) {
250 synchronized(lock5) {
251 C();
252 }
253 }
254 }
255 void C() {
256 synchronized(lock6) {
257 D();
258 }
259 }
260 void D() {
261 synchronized(lock7) {
262 try {
263 // signal to about to wait
264 count--;
265 lock7.wait();
266 } catch (InterruptedException e) {
267 throw new RuntimeException(e);
268 }
269 }
270 }
271
272 Map<String, Lock[]> LOCKED_MONITORS;
273 Lock WAITING_LOCK = lock7;
274 int OWNED_MONITORS = 6;
275 void initExpectedResult() {
276 LOCKED_MONITORS = new HashMap<String, Lock[]>();
277 LOCKED_MONITORS.put("D", new Lock[0]); // no monitored locked
278 LOCKED_MONITORS.put("C", new Lock[] {lock6});
279 LOCKED_MONITORS.put("B", new Lock[] {lock5, lock4});
280 LOCKED_MONITORS.put("A", new Lock[] {lock3, lock2, lock1});
281 this.setExpectedResult(WAITING_LOCK, OWNED_MONITORS, LOCKED_MONITORS);
282 }
283
284 }
285
286 static class Thread2 extends LockingThread {
287 Map<String, Lock[]> LOCKED_MONITORS = new HashMap<String, Lock[]>();
288 Lock WAITING_LOCK = lock8;
289 int OWNED_MONITORS = 0;
290 public Thread2() {
291 super("t2");
292 this.setExpectedResult(WAITING_LOCK, OWNED_MONITORS, LOCKED_MONITORS);
293 }
294 public void run() {
295 synchronized(lock8) {
296 try {
297 synchronized(lock7) {
298 count--;
299 }
300 lock8.wait();
301 } catch (InterruptedException e) {
302 throw new RuntimeException(e);
303 }
304 }
305 }
306 }
307
308}